什么是深拷贝和浅拷贝?
深拷贝和浅拷贝是针对于 引用类型 (Array、Object)说的:
浅拷贝
浅拷贝就是指两个对象指向同一个内存地址,其中一个改变会影响另一个
就好比一栋大厦A,有别称B,所以大厦A和大厦B其实是指同一栋大厦,因为它们的地址是一模一样的。假设这栋大厦改建了,那肯定大厦A、大厦B都会改变呐
深拷贝
深拷贝就是指复制后的新对象重新指向一个新的内存地址,两个对象改变互不影响
就好比在大厦A之外再建一栋一模一样的大厦B,两栋大厦是不同地址,当然大厦A改建,大厦B就不会变化的啦
Object 浅拷贝的常用方法
1. 简单的赋值操作
var arr1 = [1,2,3];
var arr2 = arr1;
arr1[0] = 5;
console.log(arr1); // [5, 2, 3]
console.log(arr2); // [5, 2, 3]
console.log(arr1 === arr2); // true
复制代码
2. Object.assign( { } , obj ) (第一层深拷贝,第二层是对象/数组则是浅拷贝)
这里的 第二层 是指 object 里面的 object,当 obj2 拷贝 obj1 里面的 obj 时,会是浅拷贝
var obj1 = { a: {a: "hello"}, b: 33 };
var obj2 = Object.assign({}, obj1);
obj2.a.a = "hello world";
console.log(obj1); // { a: {a: "hello world"}, b: 33 };
console.log(obj2); // { a: {a: "hello world"}, b: 33 };
console.log(obj1 === obj2); // false ,第一层是深拷贝
console.log(obj1.a === obj2.a); // true ,第二层如果还是对象则是浅拷贝
复制代码
3. 遍历原对象拷贝的方法(第一层深拷贝,第二层是对象/数组则是浅拷贝)
var obj1 = { a: {a: "hello"}, b: 20};
var obj2 = {};
var arr = Object.entries(obj1)
for(let i=0;i<arr.length;i++){
Object.defineProperty(obj2,arr[i][0],{
configurable: true,
enumerable: true,
writable: true,
// 以上三个的默认值均为 false,所以得设置为 true
value: arr[i][1]
})
}
obj2.b = 100;
console.log(obj1); // { a: 10, b: 20}
console.log(obj2); // { a: 10, b: 100};
console.log(obj1 === obj2); // false
console.log(obj1.a === obj2.a); // true
复制代码
大多数的实际情况我们都是考虑使用深拷贝的,只是我们要注意如果我们在无意间使用了浅拷贝,就会有篡改其他对象/数组的事件发生。当然有时候我们也还是会用浅拷贝的,比如说公有的对象等等
Object 深拷贝的常用方法
1. obj2 = JSON.parse(JSON.stringify(obj1))
var obj1 = { a: {a: "hello"}, b: 33 };
var obj2 = JSON.parse(JSON.stringify(obj));
obj2.b = "hello world";
console.log(obj1); // { a: "hello", b: 33 };
console.log(obj2); // { a: "hello world", b: 33};
console.log(obj1===obj2); // false
复制代码
缺点:
- 无法拷贝函数类型的属性
- 会会抛弃对象的
constructor
属性,也就是说无法追踪原来的构造函数是哪个
2. 自定义方法
由于对象里面有对象,所以不能只是停留在表层复制,得有深入,这个深入就是递归
function deepClone(obj1){
if(typeof obj1 !== "object") return; // (因为有递归)进来先判断是否为引用类型
let obj2 = obj1 instanceof Array ? [] : {}; // 判断是数组还是对象
for(let key in obj1){
if(obj.hasOwnProperty(key)){ // 拷贝原对象 obj 的自身属性就好
obj2[key] = typeof obj1[key] === "object" ? deepClone(obj1[key]) : obj1[key];
}
}
return obj2;
}
复制代码
测试:
let obj = {a: 11, b: function(){}, c: {d: 22}};
deepClone(obj); // {a: 11, b: f(), c: {d: 22}};
复制代码
Array 浅拷贝
1. 直接赋值
var arr1 = [1,2,3]
var arr2 = arr1
arr2[0] = 4
console.log(arr1) // [4,2,3]
console.log(arr2) // [4,2,3]
console.log(arr1 === arr2) // true
复制代码
2. arr2 = arr1.slice(0)(第一层深拷贝,第二层是对象/数组则是浅拷贝)
var arr1 = [1,2,{name: "Jack"}]
var arr2 = arr1.slice
arr2[0] = 4
console.log(arr1) // [1,2,{name: "Jack"}]
console.log(arr2) // [4,2,{name: "Jack"}]
console.log(arr1 === arr2) // false
console.log(arr1[2] === arr2[2]) // true
复制代码
3. arr2 = [].concat(arr1)(第一层深拷贝,第二层是对象/数组则是浅拷贝)
var arr1 = [1,2,[4,5,6]]
var arr2 = [].concat(arr1)
arr2[0] = 4
console.log(arr1) // [1,2,[4,5,6]]
console.log(arr2) // [4,2,[4,5,6]]
console.log(arr1 === arr2) // false
console.log(arr1[2] === arr2[2]) // true
复制代码
Array 深拷贝
1. arrr2 = JSON.parse(JSON.stringify(arr1))
var arr1 = [1,2,[4,5,6]]
var arr2 = JSON.parse(JSON.stringify(arr1))
console.log(arr1 === arr2) // false
console.log(arr1[2] === arr2[2]) // false
复制代码
2. 自定义方法
采用上面自定义方法实现对象深拷贝的例子(数组可以看成对象)
参考文章
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END