Javascript Javascript按值将数组传递给函数,保持原始数组不变
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14491405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript passing arrays to functions by value, leaving original array unaltered
提问by Dave Pritlove
I've read many answers here relating to 'by value' and 'by reference' passing for sending arrays to javascript functions. I am however having a problem sending an array to a function and leaving the original array unaltered. This example llustrates the problem:
我在这里阅读了许多有关“按值”和“按引用”传递将数组发送到 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;
}
I can't understand why anything in this function should alter the original array.
我不明白为什么这个函数中的任何东西都应该改变原始数组。
calling this function directly changes the original array if the function call is assigned to a new array:
如果将函数调用分配给新数组,则调用此函数会直接更改原始数组:
myArray = [["A","B","C"],["D","E","F"],["G","H","I"]];
anotherArray = new Array();
anotherArray = myFunction(myArray);
// myArray gets modified!;
I tried using .valueOf() to send the primitive:
我尝试使用 .valueOf() 发送原语:
anotherArray = myFunction(myArray.valueOf());
// myArray gets modified!;
I have even tried breaking the array down element by element and sub-element by sub-element and assigning all to a new 2-d array and the original array still gets modified.
我什至尝试将数组逐个元素和子元素逐个分解,并将所有内容分配给新的二维数组,而原始数组仍然被修改。
I have also joined the sub-elements to a string, processed them, split them back into arrays and the original array still gets modified.
我还将子元素加入一个字符串,处理它们,将它们拆分回数组,原始数组仍然被修改。
Please, does any one know how I can pass the array values to a function and not have the passed array change?
请问,有人知道如何将数组值传递给函数而不更改传递的数组吗?
回答by Ja?ck
Inside your function there's this:
在你的函数里面有这个:
funcArray = new Array();
funcArray = someArray;
This won't actually copy someArraybut instead reference it, which is why the original array is modified.
这实际上不会复制someArray而是引用它,这就是修改原始数组的原因。
You can use Array.slice()to create a so-called shallow copy of the array.
您可以使用Array.slice()创建数组的所谓浅拷贝。
var funcArray = someArray.slice(0);
The original array will be unaltered, buteach of its elements would still reference their corresponding entries in the original array. For "deep cloning" you need to do this recursively; the most efficient way is discussed in the following question:
原始数组将保持不变,但其每个元素仍将引用其在原始数组中的相应条目。对于“深度克隆”,您需要递归执行此操作;最有效的方法在以下问题中讨论:
What is the most efficient way to deep clone an object in JavaScript?
在 JavaScript 中深度克隆对象的最有效方法是什么?
Btw, I've added varbefore funcArray. Doing so makes it local to the function instead of being a global variable.
顺便说一句,我增加var之前funcArray。这样做使其成为函数的局部变量,而不是全局变量。
回答by Tyler Hughes
Make a copy of the array that you can use.
制作您可以使用的阵列的副本。
A simple way to do this is by using var clone = original.slice(0);
一个简单的方法是使用 var clone = original.slice(0);
回答by alex
A variable pointing to an array is a reference to it. When you pass an array, you're copying this reference.
指向数组的变量是对它的引用。当你传递一个数组时,你就是在复制这个引用。
You can make a shallow copy with slice(). If you want a full depth copy, then recurse in sub objects, keeping in mind the caveats when copying some objects.
您可以使用slice(). 如果你想要一个完整的深度复制,那么在子对象中递归,记住复制一些对象时的注意事项。
回答by Bardr
What about destructuring assignment(ES6+, check compatibility)? Nice and clean solution.
解构赋值怎么样(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});
回答by Sandeep Gantait
by default in javascript except objects and arrays, everything is copy-by-value but if you want to use copy-by-value for arrays: use [yourArray].slice(0) and for objects use Object.assign(target, ...sources)
默认情况下,在 javascript 中,除了对象和数组之外,一切都是按值复制的,但是如果您想对数组使用按值复制:使用 [yourArray].slice(0) 并且对于对象使用 Object.assign(target, . ..来源)
回答by Nick Parsons
With ES6, you can use the spread syntaxand destructuringto perform a shallow copy directly in the argument list, allowing you to keep the original array unaltered.
使用 ES6,您可以使用扩展语法和解构直接在参数列表中执行浅拷贝,从而保持原始数组不变。
See example below:
请参阅下面的示例:
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
回答by Split Your Infinity
A generic solution would be...
一个通用的解决方案是......
// Use the JSON parse to clone the data.
function cloneData(data) {
// Convert the data into a string first
var jsonString = JSON.stringify(data);
// Parse the string to create a new instance of the data
return JSON.parse(jsonString);
}
// An array with data
var original = [1, 2, 3, 4];
function mutate(data) {
// This function changes a value in the array
data[2] = 4;
}
// Mutate clone
mutate(cloneData(original));
// Mutate original
mutate(original);
This works for objects as well as arrays.
这适用于对象和数组。
Very effective when you need deep cloning or you don't know what the type is.
当您需要深度克隆或不知道类型是什么时非常有效。
Deep cloning example...
深度克隆示例...
var arrayWithObjects = [ { id: 1 }, { id: 2 }, { id: 3 } ];
function mutate(data) {
// In this case a property of an object is changed!
data[1].id = 4;
}
// Mutates a (DEEP) cloned version of the array
mutate(cloneData(arrayWithObjects));
console.log(arrayWithObjects[1].id) // ==> 2
Warnings
警告
Using the JSON parser to clone is not the most performant option!
It doesn't clone functions only JSON supported data types
Cannot clone circular references
使用 JSON 解析器进行克隆并不是最高效的选择!
它不克隆函数仅支持 JSON 的数据类型
无法克隆循环引用
回答by doublejosh
If you need to do this with an object, try this fancy trick...
如果你需要用一个对象来做这件事,试试这个花哨的技巧......
MY_NEW_OBJECT = JSON.parse(JSON.stringify(MY_OBJECT));
回答by Elisha McNutt
var aArray = [0.0, 1.0, 2.0];
var aArrayCopy = aArray.concat();
aArrayCopy[0] = "A changed value.";
console.log("aArray: "+aArray[0]+", "+aArray[1]+", "+aArray[2]);
console.log("aArrayCopy: "+aArrayCopy[0]+", "+aArrayCopy[1]+", "+aArrayCopy[2]);
This answer has been edited. Initially I put forth that the newoperator handled the solution, but soon afterward recognized that error. Instead, I opted to use the concat() method to create a copy. The original answer did not show the entire array, so the error was inadvertently concealed. The new output shown below will prove that this answer works as expected.
此答案已被编辑。最初我提出new操作员处理了解决方案,但很快就意识到了这个错误。相反,我选择使用 concat() 方法来创建副本。原来的答案没有显示整个数组,所以不经意间隐藏了错误。下面显示的新输出将证明此答案按预期工作。
aArray: 0, 1, 2
aArrayCopy: A changed value., 1, 2

