理解深浅拷贝先理解什么是引用类型:
引用类型与值类型的区别:
值类型:var a = ‘hello’;var b = a;//值类型直接复制
引用类型:var a = {x:1,y:2}
引用类型的变量(a)是一个对象({x:1,y:2})内存地址的指针,引用类型是指存储在内存中的对象,通过引用(即访问内存地址)来访问这些对象
浅拷贝
只复制对象的第一层属性,嵌套对象仍然共享引用。
第一属性的解释:嵌套对象外的属性称为第一属性。
语法:Object.assign({}, obj1);解析:浅拷贝方法,参数1定义数据类型,图中为一个对象花括号,参数2,定义所拷贝的对象。参考如下代码:
let obj1 = { name: "Kimi", address: { city: "Beijing" } };
let obj2 = Object.assign({}, obj1);
obj2.address.city = "Shanghai";
console.log(obj1); // 输出 { name: "Kimi", address: { city: "Shanghai" } }
代码逻辑:定义了两个引用类型obj1和obj2,obj2浅拷贝了obj1,代码中修改了obj2.address.city的值,后面输出obj1对象,结果表示了在浅拷贝中嵌套对象的修改会共享引用,而且第一属性的修改不会共享,即各自值类型的修改不会互相影响。
深拷贝
完全复制对象及其嵌套对象。与浅拷贝相比,第一属性和嵌套对象的修改不会共享引用。
语法:JSON.parse(JSON.stringify(obj1));
分解说明:JSON.stringify(obj1),把对象那个obj1转换为json字符串,然后
JSON.parse,将json字符串转换为json对象。组合起来实现深拷贝。
参考代码:
let obj1 = { name: "Kimi", address: { city: "Beijing" } };
let obj2 = JSON.parse(JSON.stringify(obj1));
obj2.address.city = "Shanghai";
console.log(obj1); // 输出 { name: "Kimi", address: { city: "Beijing" } }
代码逻辑:定义了两个引用类型obj1和obj2,obj2深拷贝了obj1,代码中修改了obj2.address.city的值,后面输出obj1对象,结果表示了在深拷贝中第一属性和嵌套对象的修改不会共享引用。
深拷贝的多种使用
第一种使用json字符串转换实现深拷贝,
第二种通过递归手搓实现深拷贝
第三种利用lodash.js库里面的”_.cloneDeep”,此处未做演示。
下面使用递归实现深拷贝。
<script>
// 声明一个对象,实现深拷贝
// 深拷贝:对象的属性值是基本数据类型,直接赋值即可
let obj = {
uname: "zhangsan",
age: 20,
hobby: ['sing', 'dancing']
}
let o = {}
// 定义一个深拷贝方法,参数:新对象,旧对象
function deepCopy(newobj, oldobj) {
for (let k in oldobj) {
// 处理嵌套对象的问题,如果属性值是对象或者数组,则继续递归,即执行本函数
if (oldobj[k] instanceof Object) {
newobj[k] = []
deepCopy(newobj[k], oldobj[k])
} else {
//如果属性值是基本数据类型,直接赋值
newobj[k] = oldobj[k]
}
}
}
deepCopy(o, obj);
o.age = 22
o.hobby[0] = 'rap'
console.log(o); // {uname: 'zhangsan', age: 22, hobby:['rap', 'dancing']}
console.log(obj); // {uname: 'zhangsan', age: 20, hobby:['sing', 'dancing']}
</script>
代码逻辑:声明一个对象obj,内置有一个嵌套对数组对象hobby,,以及另一个空值对象o,定义一个深拷贝的方法,包含有两个参数,for循环遍历旧对象,循环判断旧对象属性值是一个对象,还是基本数据类型;如果是一个对象,那么将设置参数新对象为一个空值对象,递归该深拷贝方法循环判断并赋值,否则直接赋值。尝试修改对象o的属性值,可以发现,对象obj的属性值不会受影响,由此深拷贝得以实现。
799

被折叠的 条评论
为什么被折叠?



