当前位置: > > > JS - 对象、数组复制的几种方法(深拷贝)

JS - 对象、数组复制的几种方法(深拷贝)

JavaScript 并没有直接提供对象或者数组的复制方法。比如下面的代码,我们改变对象 b 的时候,对象 a 也会同时改变。
var a = {v1:1, v2:2};
var b = a;
b.v1 = 3;
console.log("对象a:", a);
console.log("对象b:", b);
控制台输出如下:

这是由于对象之间的赋值,只是将地址指向同一个,而不是真正意义上的拷贝。下面分别演示如何实现对象、数组的深拷贝,这样新生成的对象与原对象相互独立,不会互相影响。

一、数组的浅拷贝

浅拷贝(浅克隆):指的是只拷贝第一层的原始类型值,和第一层的引用类型地址。数组的 Array.prototype.slice() Array.prototype.concat() 方法可以实现浅拷贝。

1,使用 slice 方法实现

var objects = [{ 'a': 1 }, { 'b': 2 }, { 'c': 3 }];
var shallows = objects.slice(0);
 
objects.pop(); //移除最后一个元素
objects[0].a = 11111; // 修改第一个元素值
 
console.log(objects);
console.log(shallows);
运行结果如下:

2,使用 concat 方法实现

var objects = [{ 'a': 1 }, { 'b': 2 }, { 'c': 3 }];
var shallows = objects.concat();
 
objects.pop(); //移除最后一个元素
objects[0].a = 11111; // 修改第一个元素值
 
console.log(objects);
console.log(shallows);

3,使用 Lodash 工具库

Lodash 是一个 JavaScript 实用工具库,使用它的 clone 方法可以实现对象、数组等的浅拷贝(浅克隆):
关于 Lodash 浅拷贝更详细的用法可以参考我写的另一篇文章:
var objects = [{ 'a': 1 }, { 'b': 2 }, { 'c': 3 }];
var shallows = _.clone(objects);

objects.pop(); //移除最后一个元素
objects[0].a = 11111; // 修改第一个元素值

console.log(objects);
console.log(shallows);

二、对象、数组的深拷贝

深拷贝(深克隆):指拷贝所有的属性值,以及属性地址指向的值的内存空间。

1,通过对象序列化实现

我们可以将对象序列化再解析回来实现对象拷贝(注意:对象中的函数 function 不会被复制)
var a = {v1:1, v2:2};
var b = JSON.parse(JSON.stringify(a));
b.v1 = 3;
console.log("对象a:",a);
console.log("对象b:",b);

运行结果如下:

2,通过递归遍历实现

(1)我们定义一个 clone 方法实现深度复制功能(Deep Copy),其内部实现原理就是将对象、数组的属性遍历一遍,赋给一个新的对象。
//自定义的复制方法
function clone(obj) {
  var copy = {};
  for (var attr in obj) {
    copy[attr] = typeof(obj[attr])==='object' ? clone(obj[attr]) : obj[attr];
  }
  return copy;
}

//测试样例
var a = {v1:1, v2:2};
var b = clone(a);
b.v1 = 3;
console.log("对象a:",a);
console.log("对象b:",b);

(2)也可以直接给 Object 增加个 clone 方法,其内部实现原来同上面是一样的。
//自定义的复制方法
Object.prototype.clone = function() {
  var copy = (this instanceof Array) ? [] : {};
  for (var attr in this) {
    if (this.hasOwnProperty(attr)){
      copy[attr] = typeof(this[attr])==='object' ? clone(this[attr]) : this[attr];
    }
  }
  return copy;
};

//测试样例
var a = {v1:1, v2:2};
var b = a.clone();
b.v1 = 3;
console.log("对象a:",a);
console.log("对象b:",b);

3,使用 jQuery 复制

jQuery 自带的 extend 方法可以用来实现对象的复制。
var a = {v1:1, v2:2};
var b = {};
$.extend(b,a);
b.v1 = 3;
console.log("对象a:",a);
console.log("对象b:",b);

4,使用 Lodash 工具库

Lodash 是一个 JavaScript 实用工具库,使用它的 cloneDeep 方法可以实现对象、数组等的深拷贝(深克隆):
关于 Lodash 深拷贝更详细的用法可以参考我写的另一篇文章:
var object = { 'a': 1, 'b': { 'c':2, 'd':3 } };
var shallow = _.cloneDeep(object);

object.a = 1111;
object.b.c = 2222;

console.log(object);
console.log(shallow);
评论0