对象拷贝
在 jQuery 中如果想要将某个对象拷贝(合并)给另外一个对象可以使用使用 $.extend()
方法实现。
语法:$.extend( [deep], target, object0[, objectN] );
- deep:如果设置为 true 为深拷贝,flase 则为浅拷贝,默认为 false 。
- target:拷贝内容Object类型,目标对象,其他对象的成员属性将被附加到该对象上
- object0:待拷贝的第一个对象。
- objectN:待拷贝的第 N 个对象。
- 浅拷贝目标对像引用的被拷贝对象地址,修改目标对象会影响被拷贝对象。
- 深拷贝,deep 为 true ,完全克隆,修改目标对象不会影响被拷贝对象。
注意:
- 不支持第一个参数传递 false 。
- 如果只为 $.extend() 指定了一个参数,则意味着参数 target 被省略。此时, target 就是 jQuery 对象本身。
- 如果多个对象具有相同的属性,则后者会覆盖前者的属性值。
- 如果多个对像中有相同的复杂类型属性浅拷贝后者会覆盖前者的属性值,深拷贝则会将他们的属性值进行合并。
<script>
var targetObj = {} // 声明一个空对象来接收合并后的对象(target)
var obj0 = {
name: '冯绍峰',
index: 0,
girlFriend: {
gfName: '赵丽颖',
gfAge: 23,
}
};
var obj1 = {
name: '猪八戒',
age: 28,
girlriend: {
gfName: '嫦娥',
gfWeight: 100,
}
};
$.extend(targetObj, obj0, obj1);
// 先将 obj0 拷贝给 targetObj 后,再将 obj1 拷贝给 targetObj;
//注意均为浅拷贝,出现冲突的属性无论是否是复杂数据类型都会会直接覆盖原有属性值。
console.log(targetObj); // 输出如图1
// $.extend(true, targetObj, obj0, obj1);
// 这个是深拷贝所以如果冲突属性的属性值是复杂数据类型不会直接覆盖。
// console.log(targetObj); // 输出如图2
</script>
图1:浅拷贝时两对象无论是简单数据类型还是复杂数据类型如果不冲突则合并(拷贝),如果冲突就后者覆盖前者。
图2:深拷贝时两对象的简单数据类型和浅拷贝一致,但是复杂数据类型的属性冲突时并不是直接覆盖。
原理:
有关深拷和浅拷贝的详细机制个人想在后面的 javascript 面向对象编程中再做探讨和总结。现在先大概了解。理解有什么错误,希望看到的大佬指正。
图1:声明三个对象(复杂数据类型)变量,在栈内存开辟三个内存空间分别存放三个指向不同堆内存的地址。在堆内存中如果属性是复杂数据类型则存储一个指向其他内存空间的地址。(如 #ccaa00 , #ccdc00)
图2:进行第一轮浅拷贝时,将 obj0 的所有内容都拷贝保存到 targetObj 的堆内存空间中,注意此时 targetObj.girlFriend 对象并没有重新开辟内存空间而是将 obj0.girlFriend 保存的内容(地址)拷贝过来,所以与 obj0.girlFriend 指向同一内存空间。
图3:进行第二轮浅拷贝时,将 obj1 的所有内容都复制保存到 targetObj 的堆内存空间中(重复的属性将重新赋值),注意此时将 obj1.girlFriend 保存的内容(地址)拷贝过来对 targetObj.girlFriend 重新赋值,所以 targetObj.girlFriend 与 obj1.girlFriend 指向同一内存空间。
图4:进行第一轮深拷贝时,将 obj0 的所有内容都复制保存到 targetObj 的堆内存空间中,此时 obj0.girlFriend 对象是复杂数据类型,系统会重新开辟内存空间并将其内容拷贝至新的内存空间,targetObj.girlFriend 中则保存了该新空间的地址。
图5:进行第二轮深拷贝时,将 obj1 的所有内容都复制保存到 targetObj 的堆内存空间中(重复的属性将重新赋值)。对于 girlFriend 属性是复杂对象则会根据地址(#ccaaff)找到相应的内存空间并将 obj1.girlFriend 的内容拷贝给 targetObj.girlFriend (重复的属性将重新赋值)。
以上即是我对拷贝的理解,如果有误希望大佬指出,如果你也是这么想的或者对你有帮助请给个赞(滑稽脸)。