拷贝功能是编程中的一个常用操作,主要分为深拷贝和浅拷贝,但也是经常容易犯错的一个知识点,今天来谈谈Javascript中的拷贝功能。
在JS中,常见的字符串拷贝操作是这样的:
str1 = '123';
str2 = str1;
console.log(str1);
str2 = '456';
console.log(str1);
console.log(str2);
非常简单,输出结果如下:
123
123
456
下面来看一段浅拷贝的例子:
obj1 = {a: 1};
obj2 = obj1;
console.log(obj2.a);
obj2.a = 2;
console.log(obj2.a);
console.log(obj1.a);
输出结果:
1
2
2
上面的代码可以看到,当我们把obj1赋值给obj2的后,改变了obj2中属性a的值,发现obj1中的a同样被改变了,因为当把obj1赋值给obj2后,obj1和obj2指向了同一个地址,这时候obj2和obj1是共享同一个内存空间的,可以参考下面的这种图:
所以改变obj2中的a,相当于改变了obj1中的a,这就是浅拷贝;
接着来看下深拷贝如何实现:
obj1 = {a: 1, b: {c: 2}};
obj2 = JSON.parse(JSON.stringify(obj1));
obj2.b.c = '3';
console.log(obj1.b.c);
输出结果:
2
可以看到通过把对象进行1次序列化+反序列化,把obj1赋值给obj2,然后修改obj2对象中的属性值,最后发现obj1中的属性值并没有改变,因为obj1和obj2独享自己的一份内存空间,这就实现了深拷贝操作,可以参照下面的这张图:
但是,上面的深拷贝方式其实是有问题的,不推荐这种写法,因为这种写法不能覆盖所有的深拷贝情况,来看几个反例:
反例1: 当要拷贝的对象中包含undefined的属性
obj1 =
{
a: 1,
b:
{
c: 2,
d: undefined
}
}
obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj2)
输出结果:
{
"a": 1,
"b": {
"c": 2
}
}
从输出结果会发现拷贝后的obj2对象缺失了属性d。
反例2: 当要拷贝的对象中包含function属性
obj1 =
{
a: 1,
b:
{
c: 2,
d: function name(params) {
console.log(params);
}
}
}
obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj2)
输出结果:
{
"a": 1,
"b": {
"c": 2
}
}
从输出结果会发现拷贝后的obj2对象缺失了属性d。
反例3: 当要拷贝的对象中包含对象属性
obj1 =
{
a: 1,
b:
{
c: 2,
d: new RegExp('\w+')
}
}
obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj2)
输出结果:
{
"a": 1,
"b": {
"c": 2,
"d": {}
}
}
从输出结果会发现拷贝后的obj2对象缺失了属性d。
从上面的3个反例中可以看到JSON.parse(JSON.stringify())这种方式并不适合用来做深拷贝。
下面来介绍在Javascript中深拷贝的正确姿势:
const _ = require('lodash');
const externalObject = {
animal: 'Gator'
};
const originalObject = {
a: 1,
b: 'string',
c: false,
d: externalObject
};
const deepClonedObject = _.clonedeep(originalObject);
externalObject.animal = 'Lizard';
console.log(originalObject);
console.log(deepClonedObject);
输出结果:
{ a: 1, b: 'string', c: false, d: { animal: 'Lizard' } }
{ a: 1, b: 'string', c: false, d: { animal: 'Crocodile' } }
从输出结果可以看到,用lodash这个三方库中的clonedeep方法做到了对象的深度拷贝,拷贝后的对象和原对象做到了完全的隔离,如果要完成深拷贝的功能,推荐使用这种方式。
以上主要介绍了Javascript中深拷贝和浅拷贝的常见用法和误区。
留言与评论(共有 0 条评论) “” |