Firefox: enableChrome: enableOpera: enableSafari: enableIE: enable

JavaScript中数组和json的复制

2010
May
17
Tags: , ,
6条评论

今天和一个朋友讨论到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方法将会是很好的选择。

6 Responses to “JavaScript中数组和json的复制”

  1. 头像
    FC_lamp Reply #1

    good。。very good

  2. 头像
    lei3389 Reply #2

    多维数组复制就没戏了。。concat看似很巧妙,二维以下还是复制的指针,你试试

  3. 头像
    坚强的小展 Reply #3

    @lei3389 二维下也不是指针啊,我试过的。。。不知道你那是什么个情况。

  4. 头像
    lei3390 Reply #4

    var arr1 = [[01,02],[11,12]];
    var arr2 = [].concat(arr1);
    arr2[0][1]=888;
    console.log(arr1[0][1]); //你觉得这里还是01么?

  5. 头像
    坚强的小展 Reply #5

    @lei3390 可能我们在理解上存在一些偏差。concat 确实将连接的数组进行了深度拷贝,即便是二维数组也是如此:
    var arr1 = [[01,02],[11,12]];
    var arr2 = [].concat(arr1);
    arr2[0]=888;
    console.log(arr1[0][1]); //这里的结果确实是2
    concat 将拷贝的数组指向了新的地址,与数组内容无关,而内层的数组指向哪里并不受这个方法调用而受到影响。

我来说两句