简介
注:浅拷贝和深拷贝都只针对于像Object, Array这样的复杂对象。
浅拷贝:浅拷贝只是复制了内存地址,如果原地址中的对象改变了,浅拷贝出来的对象也会相应改变。
深拷贝:开辟了一块新的内存存放地址和地址指向的对象,原地址的任何对象改变了,深拷贝出来的对象不变。
区别:浅拷贝只复制对象的第一层属性并不包括对象里面的引用类型数据、深拷贝是对对象以及对象的所有子对象进行拷贝
浅拷贝
1.实现浅拷贝的方法
(1)for...in只循环第一层
在上面的代码中,我们创建了一个 shallowCopy 函数,它接收一个参数也就是被拷贝的对象。
- 首先创建了一个对象
- 然后 for...in 循环传进去的对象,为了避免循环到原型上面会被遍历到的属性,使用 hasOwnProperty 限制循环只在对象自身,将被拷贝对象的每一个属性和值添加到创建的对象当中
- 最后返回这个对象
这与直接赋值var obj3 = obj1的区别如下:
name | 和原数据是否指向同一对象 | 第一层数据为基本数据类型 | 原数据中包含子对象 |
---|---|---|---|
赋值 | 是 | 改变会使原数据一同改变 | 改变会使原数据一同改变 |
浅拷贝 | 否 | 改变不会使原数据一同改变 | 改变会使原数据一同改变 |
(2)ES6的Object.assign
Object.assign:用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target),并返回合并后的target
用法: Object.assign(target, source1, source2); 所以 copyObj = Object.assign({}, obj); 这段代码将会把obj中的一级属性都拷贝到 {}中,然后将其返回赋给copyObj
(3)ES6扩展运算符
扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中
(4)Array.prototype.slice()
(5)Array.prototype.concat()
.....
实现浅拷贝的方法还有很多,只需要记住浅拷贝的定义浅拷贝只是复制了内存地址,如果原地址中的对象改变了,浅拷贝出来的对象也会相应改变
深拷贝
(1)递归调用浅拷贝
对于深拷贝的对象,改变源对象不会对得到的对象有影响。只是在拷贝的过程中源对象的方法丢失了,这是因为在序列化 JavaScript 对象时,所有函数和原型成员会被有意忽略。
(2)JSON.stringify()和JSON.parse()
stringify 可以把一个 js 对象序列化为一个 JSON 字符串,parse 可以把 JSON 字符串反序列化为一个 js 对象
但是这种方法也有不少坏处,譬如它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。
这种方法能正确处理的对象只有可以转成JSON格式的对象才可以这样用( Number, String, Boolean, Array,...)