记录下js中关于浅拷贝和深拷贝的一些问题,下面是代码,可以自行复制到js文件中,逐步去掉注释查看结果,记得要用node运行。
var _ = require('lodash');
var obj1 = {
a: 1,
b: [2],
c: {
d: 3
},
e: undefined,
f: null,
g: Symbol('这是一个Symbol'),
h: () => {
return 'function'
}
}
console.time('time');
var obj2 = obj1;
// var obj2 = JSON.parse(JSON.stringify(obj1));
// var obj2 = Object.assign({}, obj1);
// var obj2 = _.cloneDeep(obj1);
console.timeEnd('time');
obj2.a = 0;
obj2.c.d = 0;
obj2.b.push(0);
console.log('----------------------------------------');
console.log('obj1:', obj1);
console.log('----------------------------------------');
console.log('obj2:', obj2);
1. 直接赋值
var obj2 = obj1;
这种方式是最常用的,也是速度最快的,但是这是属于浅拷贝,指向的是同一个内存地址,也就是如果obj2的属性改变的话,obj1也会跟着改变。
time: 0.179ms
----------------------------------------
obj1: { a: 0,
b: [ 2, 0 ],
c: { d: 0 },
e: undefined,
f: null,
g: Symbol(这是一个Symbol),
h: [Function: h] }
----------------------------------------
obj2: { a: 0,
b: [ 2, 0 ],
c: { d: 0 },
e: undefined,
f: null,
g: Symbol(这是一个Symbol),
h: [Function: h] }
2. 转成字符串再转回JSON对象
var obj2 = JSON.parse(JSON.stringify(obj1));
这种方式是属于深拷贝,速度是最快的深拷贝,也就是obj2改变任意一个属性,都不会影响obj1,但是这种方式会丢失掉undefined、Symbol和function等等的某些数据类型。
time: 0.211ms
----------------------------------------
obj1: { a: 1,
b: [ 2 ],
c: { d: 3 },
e: undefined,
f: null,
g: Symbol(这是一个Symbol),
h: [Function: h] }
----------------------------------------
obj2: { a: 0, b: [ 2, 0 ], c: { d: 0 }, f: null }
3. ES6新语法
var obj2 = Object.assign({}, obj1);
这种方式是属于特殊的深拷贝,也有人认为这是属于浅拷贝,他的速度也很快,而且不会丢失任何的数据类型,但是他只会拷贝第一层,深层的属性是无法实现深拷贝的,具体看下面的返回值。另外需要注意的是,这个方式是ES6的新语法,注意兼容性。
time: 0.198ms
----------------------------------------
obj1: { a: 1,
b: [ 2, 0 ],
c: { d: 0 },
e: undefined,
f: null,
g: Symbol(这是一个Symbol),
h: [Function: h] }
----------------------------------------
obj2: { a: 0,
b: [ 2, 0 ],
c: { d: 0 },
e: undefined,
f: null,
g: Symbol(这是一个Symbol),
h: [Function: h] }
4. Lodash插件实现
var obj2 = _.cloneDeep(obj1);
使用这个插件可以实现完整的深拷贝,但是这个插件也是最耗费资源的,是普通拷贝的5-10倍,不过他不会丢失任何任何的数据,而且实现了深层的拷贝,obj2是完全独立于obj1的。
time: 1.062ms
----------------------------------------
obj1: { a: 1,
b: [ 2 ],
c: { d: 3 },
e: undefined,
f: null,
g: Symbol(这是一个Symbol),
h: [Function: h] }
----------------------------------------
obj2: { a: 0,
b: [ 2, 0 ],
c: { d: 0 },
e: undefined,
f: null,
g: Symbol(这是一个Symbol),
h: [Function: h] }