浅拷贝:
基本类型浅拷贝拷贝的值就是基本类型的值,引用类型拷贝的是内存地址,如果内存地址改变,对象就改变了
Object.assign()
注意:
- 不会拷贝对象继承的属性
- 不可枚举的属性
- 属性的数据属性/访问器属性
- 可以拷贝Symbol类型
可以理解为Object.assign就是使用简单的=来赋值,遍历从右往左遍历源对象(sources)的所有属性用 = 赋值到目标对象(target)上
扩展运算符
利用扩展运算符可以在构造字面量对象时,进行克隆或者属性拷贝
let cloneObj = { ...obj };
Array.prototype.slice()
slice() 方法返回一个新的数组对象,这一对象是一个由 begin和 end(不包括end)决定的原数组的浅拷贝。原始数组不会被改变。
扩展运算符Object.assign()有同样的缺陷,对于值是对象的属性无法完全拷贝成2个不同对象,但是如果属性都是基本类型的值的话,使用扩展运算符更加方便
arr.slice(begin, end);
在ES6以前,没有剩余运算符,Array.from的时候可以用 Array.prototype.slice将arguments类数组转为真正的数组,它返回一个浅拷贝后的的新数组
深拷贝
浅拷贝只在根属性上在堆内存中创建了一个新的的对象,复制了基本类型的值,但是复杂数据类型也就是对象则是拷贝相同的地址,而深拷贝则是对于复杂数据类型在堆内存中开辟了一块内存地址用于存放复制的对象并且把原有的对象复制过来,这2个对象是相互独立的,也就是2个不同的地址
JSON.stringify() ===》JSON.parse()
通过JSON.stringify实现深拷贝有几点要注意
- 拷贝的对象的值中如果有函数,undefined,symbol则经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失
- 无法拷贝不可枚举的属性,无法拷贝对象的原型链
- 拷贝Date引用类型会变成字符串
- 拷贝RegExp引用类型会变成空对象
- 对象中含有NaN、Infinity和-Infinity,则序列化的结果会变成null
- 无法拷贝对象的循环应用(即obj[key] = obj)