【问题标题】:javascript pass by reference workaroundjavascript 通过引用传递的解决方法
【发布时间】:2014-02-09 21:30:11
【问题描述】:

假设我有一个数组,var animals = ["dog","cat","rat"];

然后我定义var pets = animals;

然后我打电话给pets.shift();

现在因为 javascript 是数组的传递引用,如果我现在调用 animals,我会得到 ["cat","rat"]

我的问题:如果我以后想以未经修改的形式使用animals,有什么办法吗?

【问题讨论】:

    标签: javascript pass-by-reference


    【解决方案1】:

    关于术语的说明:JavaScript 从不 pass-by-reference(无论你听到人们说多少次)。当你写这行时:

    var pets = animals;
    

    您将animals 分配给pets。分配的值是对数组的引用,因此现在两个变量 引用 到内存中的同一个对象。 (注意:这有点迂腐,但它也具有正确的优点。)

    如果您希望这两个变量引用两个不同的数组,那么您需要创建原始数组的副本并将对该数组的引用分配给pets。在 JavaScript 中最常见的做法是利用一些数组方法(如 sliceconcat)创建调用它们的数组的副本:

    var pets = animals.concat();
    

    不等式证明:

    var arr = [];
    arr1 = arr;
    console.log(arr1 === arr); // true
    console.log(arr1 === arr.concat()) // false
    

    当然,你也可以自己执行复制:

    function copy(arr) {
        var i, len = arr.length, arr1 = new Array(len);
        for (i = 0; i < len; i += 1) {
            arr1[i] = arr[i];
        }
        return arr1;
    }
    

    确实,this is probably a lot faster 应该考虑用于非常大的数组。 (在大多数情况下,只做最易读的事情。)

    请注意,这些方法中的每一个都会创建原始数组的浅层副本。如果数组包含对其他对象的引用,那么这些引用将被复制到新数组(即原始数组和新数组都将引用相同的对象)。另一方面,字符串和数字被直接复制到新数组中。

    【讨论】:

    • 感谢您的详尽回答。一个微妙的区别,我会花一些时间思考一下。
    • so - 如果复制的数组包含和对象,然后对其进行修改,我可能会遇到同样的问题。
    • 是的。你可能想看这里:stackoverflow.com/questions/122102/…
    • @GregoryTippett:“如果复制的数组包含和对象”数组不能“包含对象”,因为“对象”不是值。数组只能包含引用(指向对象的指针)。
    【解决方案2】:

    你必须克隆数组,这是用

    var savedAnimals = animals.slice();
    

    请注意,这不是深度克隆:它不会保护内部元素不被修改(如果它们不是字符串)。

    【讨论】:

    • 这是最好的,也是标准的。
    猜你喜欢
    • 2021-07-29
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 2011-11-01
    • 2012-05-20
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    相关资源
    最近更新 更多