生命不息,学习不止

js常用的几种拷贝方法的优缺点

记录下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] }

赞(1)
未经允许不得转载:Mxue note » js常用的几种拷贝方法的优缺点