深拷贝与浅拷贝是面试中出现频率很高的问题。现在说说原理。
如何区分:深拷贝与浅拷贝。
简单点来说,就是假设把一个对象A复制了另一个对象B,当修改A的属性值发生变化时,看看对象B对应的属性值否会发生相同变化,如果B的属性值也跟着变了,说明这是浅拷贝,如果B的属性值没变,那就是深拷贝。
举个浅拷贝例子:
这是浅拷贝。原理是testB指向了testA的对象的地址。testA,testB指向同一块内存空间。
如何实现深拷贝?
解决方案
1.JSON.parse(JSON.stringify)
,缺点: 丢失成员函数。
问题:b对象的属性nowDate,在a对象原本是时间对象,现在变成字符串。
2.Object.assign
,缺点: 只有第一级深拷贝,子级对象依旧是浅拷贝。
实现JS深拷贝函数
- 递归遍历调用拷贝函数
- 直到当前值类型时null或者非object类型,return退出本次递归
- 把当前基础类型数据值作为属性返回给上一级。
let a = {
test: {
value: '1'
},
nowDate: new Date()
};
let b = deepCopy(a);
console.log(a);
console.log(b);
b.test.value = '2';
console.log(a);
console.log(b);
function deepCopy(obj) {
let result = obj;
debugger;
if(typeof obj === 'object' && obj !== null) {
result = Object.prototype.toString.call(obj) === '[object Array]' ? [] : {};
for(let prop in obj) {
result[prop] = deepCopy(obj[prop]);
}
}
return result;
}
结果
问题分析:
递归 __proto__属性时,获取的是Object的__proto__。
不能实现JS内置的包装对象Number,String,Boolean,RegExp,Date对象的拷贝。
具体解决方案,网上大多是调用包装对象的valueOf()方法。
更优的方案研究中........