js浅拷贝与深拷贝(2017.09.04)
aermin opened this issue · comments
深浅拷贝区别
深拷贝和浅拷贝只针对像 Object, Array 这样的复杂对象(引用类型)的。
复制引用(引用类型)的拷贝方法称之为浅拷贝,也因为直接复制引用类型,导致新旧对象共用一块内存地址,会互相影响,具体看例子
深拷贝就是指完全的拷贝一个对象,将原对象的各个属性递归复制下来。这样即使嵌套了对象,两者也相互分离。
浅拷贝
var shallowCopy = function(obj) {
if (typeof obj !== 'object') return; // 只拷贝对象
var newObj = obj instanceof Array ? [] : {}; // 根据obj的类型判断是新建一个数组还是对象
for (var key in obj) { // 遍历obj,并且判断是obj的属性才拷贝
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}
var obj = { a:1, arr: [2,3] };
var shallowObj = shallowCopy(obj);
shallowObj.arr[1] = 5;
console.log(obj.arr[1]) // 5
shallowObj.a = 5;
console.log(obj.a) // 1
备注:
①hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性。Object.prototype.hasOwnProperty(),;
②instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。换种说法就是如果左侧的对象是右侧类的实例, 则表达式返回true, 否则返回false 。
原理
遍历对象,然后把属性和属性值都放在一个新的对象
具体:判断是参数否为对象,是数组还是object;用 for in 遍历所传的参数对象,并用 if (arg.hasOwnProperty(prop)) 忽略掉继承属性,然后赋值给临时创建的对象,最后返回此对象。
深拷贝
实现一个深拷贝在拷贝的时候判断一下属性值的类型,如果是对象,我们递归调用深拷贝函数就OK了
var deepCopy = function(obj) {
if (typeof obj !== 'object') return;
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
}
}
return newObj;
}
var obj = { a:1, arr: [2,3] };
var shallowObj = shallowCopy(obj);
shallowObj.arr[1] = 5;
console.log(obj.arr[1]) // 3
shallowObj.a = 5;
console.log(obj.a) // 1
性能问题
尽管使用深拷贝会完全的克隆一个新对象,不会产生副作用,但是深拷贝因为使用递归,性能会不如浅拷贝,在开发中,还是要根据实际情况进行选择。
待续:
https://www.zhihu.com/question/23031215
https://yanhaijing.com/javascript/2018/10/10/clone-deep/
https://stackoverflow.com/questions/4459928/how-to-deep-clone-in-javascript
https://segmentfault.com/a/1190000002789651