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 方法可以实现对象、数组等的浅拷贝(浅克隆):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),其内部实现原理就是将对象、数组的属性遍历一遍,赋给一个新的对象。
(2)也可以直接给 Object 增加个 clone 方法,其内部实现原来同上面是一样的。
//自定义的复制方法 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 方法可以实现对象、数组等的深拷贝(深克隆):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);