什么是深拷贝
创建一个新的对象或数组时,将原对象/数组的“值”拷贝,而不是“引用”。
深拷贝
-
数组拷贝
不存在多层嵌套的情况下,直接for遍历、slice()、concat(),都是可行的。 -
JSON.parse(JSON.stringify(XXX))
var a = [
{ name: ' dadad' },
{ age: 18 }
];
var copy_a = JSON.parse(JSON.stringify(a))
copy_a[0].name = 'ddd'
console.log(a);// dadad
console.log(copy_a);// ddd
通过JSON.stringify()序列化对象;序列化的作用就是存储对象(对象本身存储的只是一个地址映射,如果断电,对象将不复存在,因此需将对象的内容转换成字符串的形式再保存在磁盘上 ),再通过JSON.parse反序列化,申请新的地址,从而copy了对象。
但需要注意的是
-
如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象
-
如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
-
如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
-
如果obj中存在循环引用的情况也无法正确实现深拷贝
- Object.assign({},XXX)
var a = {b:undefined,c:NaN,d:'sdsd',e:function(){}}
var copy_a = Object.assign({},a)
copy_a.b = 2;
console.(copy_a);
利用ES6中的Object.assign方法,但是当obj是多层嵌套对象时,对于第一层以外的对象,则依然只是引用。
var a = {
name: {
first: 'sss' ,
}
}
var copy_a = Object.assign({},a)
copy_a.name.first = '2'
console.log(a.name.first) // 2
但需要copy的对象只是一层时,用Object.assign显然会比JSON省心许多。
- 递归拷贝
当需要拷贝的对象又是多层嵌套,又有函数等等,此时就需要我们手动写一个递归拷贝。
function copyFn(obj) {
if (obj == null) {
return null
}
var result = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === 'object') {
result[key] = copyFn(obj[key]); // 如果是对象,再次调用该方法自身
} else {
result[key] = obj[key];
}
}
}
return result;
}
网友评论