JS学习笔记——浅拷贝和深拷贝

时间:2021-09-20 19:53:54

1.浅拷贝与深拷贝

浅拷贝是指,在复制变量时,对于引用类型的变量,只拷贝其引用,不拷贝其在堆中的真实数据。深拷贝是指,拷贝堆中的数据,一个新的引用指向新拷贝出来的数据。


JS学习笔记——浅拷贝和深拷贝

2.Array的push方法是浅拷贝

判断浅拷贝还是深拷贝,一个很简单的方法就是使用全等(===),当两个对象进行比较时,只有指向同一个对象,结果才会是true。当向arr中push一个obj,全等的结果是true,说明两个引用指向的是同一个对象,arr中保存的是旧引用而不是新引用。当我们修改obj后,arr也会一起被修改。当对obj赋值null,由于obj不再是引用,而arr中还保存有引用,所以他们不相等。
我原本以为执行obj=null之后,arr中保存的对象也会没掉,其实并不是。obj是引用,让其等于null只是改变obj的指向,并不影响堆中的真实对象。由于堆中的真实对象还有arr对其引用,所以该对象不会被垃圾回收。

var arr =[];
var obj = {name:'abc',obj:{name:'new'}};
arr.push(obj);

console.log(arr[0] === obj);//true
console.log(JSON.stringify(arr[0]));
console.log(JSON.stringify(obj));

obj.name = '123';
console.log(arr[0] === obj);//true
console.log(JSON.stringify(arr[0]));
console.log(JSON.stringify(obj));

obj = null;
console.log(arr[0] === obj);//false
console.log(JSON.stringify(arr[0]));
console.log(JSON.stringify(obj));
JS学习笔记——浅拷贝和深拷贝

3.对象的深拷贝

对象深拷贝的方法就是遍历对象的属性,并把属性赋值给新对象。数组是比较特殊的对象,在拷贝数组的时候,需要初始化的是[]

function deep(src) {
var des = Array.isArray(src) ? [] : {};
for(var key in src) {
if(src.hasOwnProperty(key)) {
des[key] = src[key];
}
}
return des;
}
var des = deep(src);

上面这个拷贝方法会有一些问题:当对象的属性还是对象的时候,该属性对象会是浅拷贝。对于这种情况,我们可以递归地调用该方法。

function deep(src) {
var des = Array.isArray(src) ? [] : {};
for(var key in src) {
if(src.hasOwnProperty(key)) {
des[key] = (typeof src[key] == 'object') ? deep(src[key]) : src[key];
}
}
return des;
}
var des = deep(src);

JQuery中的浅、深拷贝。第一个参数代表是否深拷贝,第二个参数是目的对象,第三个参数是要拷贝的源对象。

%.extend({}, src);//浅拷贝
%.extend(true, {}, src);//深拷贝

上面给出的深拷贝代码解决了嵌套对象的问题,但如果属性是函数的话,该属性是浅拷贝,是对函数的引用。