什么是浅拷贝?什么是深拷贝?
这三者的区别如下,不过比较的前提都是针对引用类型
先说一个简单的概念,什么是对象赋值?
对象赋值
-
- 当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
// 对象赋值:
var obj={
name:"xuxu",
age:23
}
var obj2=obj; //赋值 是 赋的栈中的地址;
obj2.name='haha';
console.log(obj.name); //haha
console.log(obj); //{name:'haha',age:23}
浅拷贝
-
- 浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
实例:
//2.浅拷贝 :
let obj = {
name: 'xuxu',
chi() {
food: '肉'
}
}
let obj3 = qian(obj);
obj3.name = 'genggeng';
obj3.chi.food = '菜'; // 新旧对象还是共享同一块内存
function qian(item) {
let obj2 = {};
for (var i in item) {
// hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)
if (item.hasOwnProperty(i)) {
obj2[i] = item[i];
}
}
return obj2;
}
console.log('obj', obj); //obj
//Object
// chi: ƒ chi()
// name: "xuxu"
console.log('obj3', obj3); //obj3
//Object
// chi: ƒ chi()
// name: "genggeng"
深拷贝
-
- 深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
// 3.深拷贝
// let obj1 = {
// name: 'xuxu',
// arr: [1, [2, 3], 4],
// };
// let obj4 = deepClone(obj1)
// obj4.name = "gengeng";
// obj4.arr[1] = [5, 6, 7]; // 新对象跟原对象不共享内存
// // 这是个深拷贝的方法
// function deepClone(obj) {
// // if (obj === null) return obj;
// // if (obj instanceof Date) return new Date(obj);
// // if (obj instanceof RegExp) return new RegExp(obj);
// // if (typeof obj !== "object") return obj;
// let cloneObj = new obj.constructor();
// for (let key in obj) {
// if (obj.hasOwnProperty(key)) {
// // 实现一个递归拷贝
// cloneObj[key] = deepClone(obj[key]);
// }
// }
// return cloneObj;
// }
// console.log('obj1', obj1) // obj1 { name: 'xuxu', arr: [ 1, [ 2, 3 ], 4 ] }
// console.log('obj4', obj4) // obj4 { name: 'gengeng', arr: [ 1, [ 5, 6, 7 ], 4 ] }
2.1 浅拷贝
Object.assign()方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
// Object.assign(target, ...sources)
// 参数 target 目标对象。sources 源对象。
let obj = {
name: 'xuxu',
chi() {
food: '肉'
}
}
let obj2 = Object.assign({}, obj);
obj2.name = 'gengegng';
obj2.chi.food = 'cai';
console.log(obj); //{name: "xuxu", chi: ƒ}
3.1深拷贝
这也是利用JSON.stringify将对象转成JSON字符串,再用JSON.parse把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。
let arr = [1, 3, {username: ' kobe'}];
let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'duncan';
console.log(arr, arr4)