1 数组的深拷贝
方法一:遍历复制
var arr = ["a", "b"], arrCopy = [];
for (var item in arr) arrCopy[item] = arr[item];
arrCopy[1] = "c";
arr // => ["a", "b"]
arrCopy // => ["a", "c"]
考虑伪多维数组可以写成函数形式:
function arrDeepCopy(source){
var sourceCopy = [];
for (var item in source) sourceCopy[item] = typeof source[item] === ‘object’ ? arrDeepCopy(source[item]) : source[item];
return sourceCopy;
}
这种方法简单粗暴,但是利用JS本身的函数我们可以更加便捷地实现这个操作。
方法二:slice()
可以参考 W3School 对 slice() 方法的描述:slice() 方法可从已有的数组中返回选定的元素。
调用格式为:
arrayObject.slice(start,end)
方法返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。该方法并不会修改数组,而是返回一个子数组。
在这里我们的思路是直接从数组开头截到尾:
arrCopy = arr.slice(0);
arrCopy[1] = "c";
arr // => ["a", "b"]
arrCopy // => ["a", "c"]
可以看出成功创建了一份原数组的拷贝。
方法三:concat()
可以参考 W3School 对 concat() 方法的描述:concat() 方法用于连接两个或多个数组。
调用格式为:
arrayObject.concat(arrayX,arrayX,…,arrayX)
该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
使用这种方法的思路是我们用原数组去拼接一个空内容,放回的便是这个数组的拷贝:
arrCopy = arr.concat();
arrCopy[1] = "c";
arr // => ["a", "b"]
arrCopy // => ["a", "c"]
2、对象的深拷贝
而对于对象的深拷贝,没有内置方法可以使用,我们可以自己命名一个函数进行这一操作:
var objDeepCopy = function(source){
var sourceCopy = {};
for (var item in source) sourceCopy[item] = source[item];
return sourceCopy;
}
但是对于复杂结构的对象我们发现这个函数并不适用,例如:
var obj = { “a”: { “a1”: [“a11”, “a12”], “a2”: 1 }, “b”: 2 };
所以需要进行一点修改:
var objDeepCopy = function(source){
var sourceCopy = {};
for (var item in source) sourceCopy[item] = typeof source[item] === 'object' ? objDeepCopy(source[item]) : source[item];
return sourceCopy;
}
var objCopy = objDeepCopy(obj);
objCopy.a.a1[1] = "a13";
obj // => { "a": { "a1": ["a11", "a12"], "a2": 1 }, "b": 2 }
objCopy // => { "a": { "a1": ["a11", "a13"], "a2": 1 }, "b": 2 }
3、对象数组的深拷贝
如果再考虑更奇葩更复杂的情况,例如我们定义:
var obj = [{ “a”: { “a1”: [“a11”, “a12”], “a2”: 1 }, “b”: 2 }, [“c”, { “d”: 4, “e”: 5 }]];
这是一个由对象、数组杂合成的奇葩数组,虽然我们平时写程序基本不可能这么折腾自己,但是可以作为一种特殊情况来考虑,这样我们就可以结合之前说的方法去拓展拷贝函数:
var objDeepCopy = function (source) {
var sourceCopy = source instanceof Array ? [] : {};
for (var item in source) {
sourceCopy[item] = typeof source[item] === 'object' ? objDeepCopy(source[item]) : source[item];
}
return sourceCopy;
}
var objCopy = objDeepCopy(obj);
objCopy[0].a.a1[1] = "a13";
objCopy[1][1].e = "6";
obj // => [{ "a": { "a1": ["a11", "a12"], "a2": 1 }, "b": 2 }, ["c", { "d": 4, "e": 5 }]]
objCopy // => [{ "a": { "a1": ["a11", "a13"], "a2": 1 }, "b": 2 }, ["c", { "d": 4, "e": 6 }]]
这样它就可以作为一个通用函数替我们进行深拷贝操作了。