首先,我们来看一段精简的代码。
var num = 10;
var num1 = num;
console.log(num) //10
console.log(num1) // 10
num1 = 20;
console.log(num1) //20
console.log(num) //10
以上代码说明,在基本的类型中,js的赋值操作,是深拷贝了。两个变量是不相互影响的。我们再看下一段代码。
var obj1 = { x: 1, y: 2 }, obj2 = obj1;
console.log(obj1) //{x: 1, y: 2}
console.log(obj2) //{x: 1, y: 2}
obj2.x = 2; //修改obj2.x
console.log(obj1) //{x: 2, y: 2}
console.log(obj2) //{x: 2, y: 2}
这一段代码中,obj2.x被修改了之后,obj1.x的值也变了,这个就是引用类型的浅拷贝了。
浅拷贝是可以看到一模一样的值,但是会产生问题的,就是你修改一个对象的值,另一个对象的值也会发生改变的。我们为什么要拷贝,因为我们在开发的过程中,不希望修改原来的对象。
实现浅拷贝的几个方法
-
Object.assign 该方法可以用于JS对象的合并,其中一个用途就是浅拷贝。
Object.assign 的语法为:Object.assign(target, …sources)注意:
- 它不会拷贝对象的继承属性;
- 它不会拷贝对象的不可枚举的属性;
- 可以拷贝 Symbol 类型的属性。
-
扩展运算符
/* 对象的拷贝 */ const obj = { a: 1, b: { c: 1 } } const obj2 = { ...obj } obj.a = 2 console.log(obj) //{a:2,b:{c:1}} console.log(obj2); //{a:1,b:{c:1}} obj.b.c = 2 console.log(obj) //{a:2,b:{c:2}} console.log(obj2); //{a:1,b:{c:2}} /* 数组的拷贝 */ let arr = [1, 2, 3]; let newArr = [...arr]; //跟arr.slice()是一样的效果 -
concat拷贝数组.
-
slice拷贝数组。slice 方法也比较有局限性,因为它仅仅针对数组类型。slice 方法会返回一个新的数组对象,这一对象由该方法的前两个参数来决定原数组截取的开始和结束位置,是不会影响和改变原始数组的。但是,数组元素是引用类型的话,也会影响到原始数组。
浅拷贝的原理
- 对基础类型做一个最基本的一个拷贝;
- 对引用类型开辟一个新的存储,并且拷贝一层对象属性。
手写一个浅拷贝
const shalldowClone = (target) => {
if (typeof target === 'object' && target !== null) {
const cloneTarget = Array.isArray(target) ? [] : {};
for (let prop in target) {
if (target.hasOwnProperty(prop)) {
cloneTarget[prop] = target[prop];
}
}
return cloneTarget;
} else {
return target;
}
}
let obj1 = shalldowClone(obj);
console.log(obj1)
obj1.age.age = 100;
console.log(obj1)
console.log(obj)
以上就是关于浅拷贝的内容。如果有收获,欢迎大家点赞 + 收藏。