是什么:
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
为什么:
浅拷贝只解决了对象第一层拷贝的问题,如果接下去的值中还有对象的话,那么就又回到最开始的话题了,两者享有相同的地址。要解决这个问题,我们就得使用深拷贝。
怎么做:
浅拷贝
1 =
let a = {
s: 'aaa'
}
let b = a;
console.log(b === a); // true
2 展开运算符 ...
会拷贝所有的属性值到新的对象中,如果属性值是对象的话,拷贝的是地址。
let a = {
a: 'aaa',
b: {
a: 'aaa'
}
}
let b = {
...a
};
console.log(b === a); // false
console.log(b.b === a.b); // true
3 Object.assign
Object.assign 只会拷贝所有的属性值到新的对象中,如果属性值是对象的话,拷贝的是地址。
let a = {
a: 'aaa',
b: {
c: 'ccc'
}
}
let b = Object.assign({}, a);
console.log(b === a); // false //对比整个对象的话是深拷贝,因为会拷贝所有的属性值到新的对象中
console.log(b.b === a.b); // true //只对比对象属性值的话是浅拷贝
深拷贝
1 JSON.parse(JSON.stringify(object))
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE
该方法也是有局限性的:
- 会忽略
undefined - 会忽略
symbol - 不能序列化函数
- 不能解决循环引用的对象 - 报错
2 js工具库 lodash 的深拷贝函数
安装:
浏览器环境:
<script src="lodash.js"></script>
通过 npm:
$ npm i --save lodash
使用:_.cloneDeep(value)
3 自做一个递归函数去深拷贝 - 还没能处理对象带函数的情况 - 不推荐
function deepClone(obj) { //可传入对象 或 数组
// 判断是否为 null 或 undefined 直接返回该值即可,
if (obj === null || !obj) return obj;
// 判断 是要深拷贝 对象 还是 数组
if (Object.prototype.toString.call(obj) === "[object Object]") { //对象字符串化的值会为 "[object Object]"
let target = {}; //生成新的一个对象
const keys = Object.keys(obj); //取出对象所有的key属性 返回数组 keys = [ ]
//遍历复制值, 可用 for 循环代替性能较好
keys.forEach(key => {
if (obj[key] && typeof obj[key] === "object")
//如果遇到的值又是 引用类型的 [ ] {} ,得继续深拷贝
target[key] = deepClone(obj[key]); //递归
else
target[key] = obj[key]; // 仍旧是浅拷贝
})
return target //返回新的对象
} else if (Array.isArray(obj)) {
// 数组同理
let arr = [];
obj.forEach((item, index) => {
if (item && typeof item === "object")
arr[index] = deepClone(item);
else
arr[index] = item;
})
return arr
}
}
const obj = {
a: 1,
b: {
a: 2
},
c: function () {
console.log('c');
}
};
const obj2 = deepClone(obj);
console.log(obj === obj2); //false
console.log(obj.c === obj2.c); //true
遗留问题:如何深拷贝一个带函数的对象,貌似js没有提这个 - 回来解决
注意点:
序列化:js中的object转化为字符串
常用json.stringify
反序列化:json字符串转化为object
常用json.parse