Javascript按值将数组传递给函数,保持原始数组不变

IT技术 javascript arrays
2021-02-22 17:50:17

我在这里阅读了许多有关“按值”和“按引用”传递将数组发送到 javascript 函数的答案。但是,我在将数组发送到函数并保持原始数组不变时遇到问题。这个例子说明了这个问题:

function myFunction(someArray)
{
// any function that makes an array based on a passed array;
// someArray has two dimensions;
// I've tried copying the passed array to a new array like this (I've also used 'someArray' directly in the code);

funcArray = new Array();
funcArray = someArray;

var i = 0;

    for(i=0; i<funcArray.length; i++)
    {
    funcArray[i].reverse;
    }

return funcArray;

}

我不明白为什么这个函数中的任何东西都应该改变原始数组。

如果将函数调用分配给新数组,则调用此函数会直接更改原始数组:

myArray = [["A","B","C"],["D","E","F"],["G","H","I"]];
anotherArray = new Array();

anotherArray = myFunction(myArray);
// myArray gets modified!;

我尝试使用 .valueOf() 发送原语:

anotherArray = myFunction(myArray.valueOf());
// myArray gets modified!;

我什至尝试将数组逐个元素和子元素逐个分解,并将所有内容分配给新的二维数组,而原始数组仍然被修改。

我还将子元素加入一个字符串,处理它们,将它们拆分回数组,原始数组仍然被修改。

请问,有人知道如何将数组值传递给函数而不更改传递的数组吗?

6个回答

在你的函数里面有这个:

funcArray = new Array();
funcArray = someArray;

这实际上不会复制someArray而是引用它,这就是修改原始数组的原因。

您可以使用Array.slice()创建数组的所谓浅拷贝。

var funcArray = someArray.slice(0);

原始数组将保持不变,其每个元素仍将引用其在原始数组中的相应条目。对于“深度克隆”,您需要递归地执行此操作;以下问题讨论了最有效的方法:

在 JavaScript 中深度克隆对象的最有效方法是什么?

顺便说一句,我增加var之前funcArray这样做使其成为函数的局部变量,而不是全局变量。

谢谢,根据我的第二条评论, slice() 使其工作,但前提是通过循环应用于二维数组的每个外部元素。
2021-04-30 17:50:17

制作您可以使用的阵列的副本。

一个简单的方法是使用 var clone = original.slice(0);

谢谢。我发现 slice 仅在通过循环应用于每个外部元素时才有效: newArray[i] = array[i].slice()
2021-05-12 17:50:17

解构赋值怎么样(ES6+,检查兼容性)?漂亮而干净的解决方案。

function myFunction(someArray) {

  for(let i = 0; i < someArray.length; i++)
  {
    someArray[i].reverse();
  }
  
  return someArray;
}

let myArray = [["A","B","C"],["D","E","F"],["G","H","I"]];

// Using destructuring assignment.
// NOTE: We can't just use `[...myArray]` because nested arrays will still be copied by reference.
let anotherArray = myFunction([...myArray.map(nested => [...nested])]);

console.log({original: myArray, copy: anotherArray});

使用 ES6,您可以使用扩展语法解构直接在参数列表中执行浅拷贝,从而保持原始数组不变。

请参阅下面的示例:

const arr = [1, 2, 3, 4, 5];

function timesTen([...arr]) { // [...arr] shallow copy the array
  for(let i = 0; i < arr.length; i++) {
    arr[i] *= 10; // this would usually change the reference
  }
  return arr;
}

console.log(timesTen(arr));
console.log(arr); // unaltered

指向数组的变量是对它的引用。当你传递一个数组时,你就是在复制这个引用。

您可以使用slice(). 如果你想要一个完整的深度复制,然后在子对象中递归,记住复制一些对象时的注意事项。

谢谢,是的,我发现如果我依次切片每个外部元素,它现在可以工作。
2021-05-14 17:50:17