JS手写代码篇---手写浅拷贝
16、浅拷贝
如果拷贝的是基本数据类型,拷贝的就是基本数据类型的值(直接赋值),如果是引用数据类型,拷贝的就是内存地址。如果其中一个对象的引用内存地址发生改变,另一个对象也会发生变化。(动态的)
看看各种浅拷贝:
-
es6的浅拷贝 :assign
const obj1 = { a: 1, b: 2 };const obj2 = { c: 3, d: 4 };const shallowCopy1 = Object.assign({}, obj1, obj2);console.log('es6浅拷贝:', shallowCopy1); // { a: 1, b: 2, c: 3, d: 4 }
-
扩展运算符
const shallowCopy2 = { ...obj1, ...obj2 };console.log('扩展运算符浅拷贝:', shallowCopy2); // { a: 3, b: 4 }
-
数组中的方法:slice
const arr = [1, 2, 3, 4];const shallowCopy3 = arr.slice();console.log('数组slice浅拷贝:', shallowCopy3); // [1, 2, 3, 4]
-
concat:合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
const arr2 = [5, 6, 7];const shallowCopy4 = arr.concat(arr2);console.log('数组concat浅拷贝:', shallowCopy4); // [1, 2, 3, 4, 5, 6, 7]
浅拷贝的核心逻辑是:
- 判断输入是否为对象
- 如果不是对象(如
number
、string
),直接返回原值(因为基本类型不需要拷贝)。 - 如果是对象或数组,则创建一个新对象/数组。
- 如果不是对象(如
- 遍历属性并复制
- 使用
for...in
遍历对象的所有可枚举属性。 - 用
hasOwnProperty
过滤掉原型链上的属性,只拷贝自身属性。 - 将属性值直接赋给新对象(如果是对象,则保持引用)。
- 使用
代码:
function shallowCopy(obj) {// 判断obj是否为对象,只拷贝对象if (!obj || typeof obj !== 'object') {return obj;}// 判断obj的类型const newObj = Array.isArray(obj) ? [] : {};// 进行遍历,是obj的属性我们才进行拷贝// 仅对对象和数组及逆行拷贝for (let key in obj) {if (obj.hasOwnProperty(key)) {newObj[key] = obj[key];}}// 返回 newObj;return newObj;}
浅拷贝的局限性:
浅拷贝只能处理一层的拷贝:
- 如果对象的属性是嵌套对象,浅拷贝只会复制引用,而不是新对象。