JavaScript中数组和json的复制
今天和一个朋友讨论到JavaScript中一些引用数据类型的复制问题,由于引用数据类型是传址复制,如果想达到真正的“复制”效果(即修改一个变量的值不会影响另一个的值),就不能使用像 var b = a; 这样的语句,对于引用类型来说,这样复制的结果就是当a的值发生变化时,b也会发生同样的变化,因为这时a真正的值只是对一个地址的引用,b复制到的也只是这个相同地址的引用而已,于是当a和b其中一个被修改之后,另一个也随之改变,有些时候这并不是我们想要的。
这样的问题遇到最多的就是在处理数组和json对象时。对于数组,我们有很方便的内置方法可以使用:
var arrayA = [1,2];
var arrayB = arrayA.concat();
arrayA[0] = [2];
//数组arrayA 被修改之后,arrayB依然维持之前拷贝的值
console.log(arrayA);
console.log(arrayB);
上面的代码中,核心只有一个方法: concat,对于数组而言,这个方法在传入数组类型的参数时用于合并两个或多个数组,在不传参数时,将原数组拷贝到一个新的地址,并返回这个新地址的引用。
json的情况稍微麻烦一点,在原生JavaScript中似乎并没有直接提供这样的方法,好在手工达到这一目的并不需要花费什么精力:
var objA = {"val" : {"name" : "myName"}};
var objB = {}; //创建一个新的json对象,用于接收objA的值
for(var i in objA){
//遍历objA,将其中的每一组“键值”原样拷贝到objB中
//不用担心多维的情况,它不会带来任何问题
objB[i] = objA[i];
}
var objA["val"] = {"name" : "yourName"};
console.dir(objA);
console.dir(objB);
//这是objB已经完全拷贝了objA
//而objA再改变也不会对objB产生影响
如果你有更好的办法,非常欢迎指出来和大家一起分享。
PS. 如果你正在使用jQuery框架,那么extend方法将会是很好的选择。

good。。very good
多维数组复制就没戏了。。concat看似很巧妙,二维以下还是复制的指针,你试试
@lei3389 二维下也不是指针啊,我试过的。。。不知道你那是什么个情况。
var arr1 = [[01,02],[11,12]];
var arr2 = [].concat(arr1);
arr2[0][1]=888;
console.log(arr1[0][1]); //你觉得这里还是01么?
@lei3390 可能我们在理解上存在一些偏差。concat 确实将连接的数组进行了深度拷贝,即便是二维数组也是如此:
var arr1 = [[01,02],[11,12]];
var arr2 = [].concat(arr1);
arr2[0]=888;
console.log(arr1[0][1]); //这里的结果确实是2
concat 将拷贝的数组指向了新的地址,与数组内容无关,而内层的数组指向哪里并不受这个方法调用而受到影响。