JavaScript中函数内的.push()会覆盖全局变量

4
我遇到了与.push()方法相关的问题:
var myArray = ["a", "b", "c", "d"];

function add(arr) {
    arr.push("e");
    return arr;
}

add(myArray);

// myArray is now  ["a", "b", "c", "d", "e"]

为什么它会覆盖myArray?我不理解...

参见:https://dev59.com/5nRB5IYBdhLWcg3wxZ7Y - Shog9
我添加了一种替代方案。当你使用.slice()时,你需要复制数组,存储它,.push()新值进去,然后返回副本。我使用了.concat(),它可以让你传入原始数组,并一次性执行所有上述步骤。 - user113716
2个回答

9

Javascript中的数组(以及大多数其他语言)是按引用传递的。

当你写add(myArray)时,你传递了一个引用到全局变量myArray所指向的同一个数组实例。
对数组对象所做的任何更改都将通过两个引用可见。

要复制实际的数组实例,请写add(myArray.slice());
请注意,这不会复制其中的对象。


有没有简单的方法来避免这种情况? - Jany
@Jany: 你无法强制将数组按值传递 - 你必须复制它,然后像SLaks演示的那样将副本作为引用传递。 - BoltClock
4
您可以通过编写 add(myArray.slice()); 来传递数组的副本。 - SLaks
我认为使用切片方法非常简单。 - Zafer
但是如果我在函数内部编写arr = "";myArray不会发生变化。这只发生在方法中吗? - Jany
@Jany:通过编写 arr = "",您正在重新分配 变量 以引用新实例。这不会影响 arr 曾经引用的原始数组实例。 - SLaks

4
如果您需要嵌套数组,那么我会更改 .add() 函数,使 .concat() 将 Array 复制到一个变量中,.push() 新值到新的 Array 中,并返回它。
function add(arr) {
    var newArr = arr.concat(); // duplicate
    newArr.push("e");      // push new value
    return newArr;         // return new (modified) Array
}

你也可以使用concat(),并返回它创建的新数组。
var myArray = ["a", "b", "c", "d"];

function add(arr) {
    return arr.concat("e");
}
var newArray = add(myArray);

console.log( newArray );  // ["a", "b", "c", "d", "e"]
console.log( myArray );   // ["a", "b", "c", "d"]

因此,您可以使用一个方法.concat()来完成两个方法.slice().push()的工作。

这还使您可以传递另一个数组而不是字符串,例如:

return arr.concat(["e","f"]);

我会为您提供:

// ["a", "b", "c", "d", "e", "f"]

改为:

// ["a", "b", "c", "d", ["e", "f"] ]

这很好,谢谢!但我需要把另一个数组放进去...这行不通 :( arr.concat([["e","f"]]); - Jany
@Jany - 我更新了我的答案,使用.push()将值推入重复项中。你只需将原始数组传递到.add()中,它会处理内部的重复项。这样,在.add()内部,你就可以访问两个数组,旧的和新的。 - user113716

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接