我们知道,在JavaScript中复制一个基本类型的值很容易实现,但如果要复制的值是一个引用类型(如Object类型),又是如何实现的呢?今天介绍一下复制对象的方法。
1、对象浅度拷贝
如图:下面声明了一个对象obj1。
var obj1 = {
name: 'zs',
age: 18,
sex: '男',
}
var obj2 = {};
function copy(o1, o2) {
for (var key in o1) {
o2[key] = o1[key];
}
}
copy(obj1, obj2);
// 修改obj1中的成员,obj2不会发生改变
obj1.name = 'lisi';
console.log(obj2.name); // zs
但浅拷贝会遇到一个问题,当待拷贝对象的成员的数据类型为引用类型时,浅拷贝之后,改变原对象中的引用类型成员,新对象也会发生改变。
var obj1 = {
name: 'zs',
age: 18,
sex: '男',
dog: {
name: '金毛',
age: 2,
yellow: '黄色'
}
}
var obj2 = {};
function copy(o1, o2) {
for (var key in o1) {
o2[key] = o1[key];
}
}
copy(obj1, obj2);
// 修改obj1中的引用类型成员,obj2也会发生改变
obj1.dog.name = '大黄';
console.log(obj2.dog.name); //大黄
为什么会发生这种现象呢?要明白这一点,首先要理解什么是浅拷贝。
当待拷贝的成员是一个引用类型,如Object类型。在复制该成员时,只是把该成员所指向的对象的地址值复制了一份,让新的变量指向原来的对象。并没有在内存中创建出一个新的对象。
换句话说,浅拷贝把一个对象的成员复制给另一个对象时,只能把第一层的值复制过去,如果该值是个对象,复制的仅仅是该对象的引用。而没有创建一个新的对象。所以改变原对象该值的属性,第二个对象也会发生改变。
2、对象深度拷贝
在进行深度拷贝时,要对对象的成员属性是否为引用类型进行判断,如果是,需要创建一个新的引用类型变量,再遍历要拷贝的引用类型成员,利用递归,直至不再出现引用类型的成员。
<script>
var obj1 = {
name: 'zs',
age: 18,
sex: '男',
dog: {
name: '金毛',
age: 2
},
friends: ['李四', 'ww']
}
// 深度拷贝的方法
function deepCopy(obj) {
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
if (typeof obj[key] === 'object') {
newObj[key] = deepCopy(obj[key]);
} else {
newObj[key] = obj[key];
}
}
return newObj
}
var obj2 = deepCopy(obj1) ;
// 修改obj1中的成员 obj2没有发生改变
obj1.dog.name = '二哈';
obj1.friends[0] = '成龙';
console.log(obj2.dog.name);//金毛
console.log(obj2.friends[0])//李四
</script>
好的,以上就是我对JavaScript中复制一个引用类型的值的理解,如有错误之处,还望同仁指出。
网友评论