Javascript передает массивы функциям по значению, оставляя исходный массив неизменным
Я прочитал здесь много ответов, касающихся передачи "по значению" и "по ссылке" для отправки массивов в функции 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!;
Я даже попробовал разбить массив на элементы и субэлементы и присвоить все Новому 2-d массиву, а исходный массив все равно модифицируется.
Я также присоединил подэлементы к строке, обработал их, разделил их обратно на массивы, и исходный массив все еще модифицируется.
Пожалуйста, кто-нибудь знает, как я могу передать значения массива в функцию и не изменился ли переданный массив?
6 ответов:
Внутри вашей функции есть следующее:
funcArray = new Array(); funcArray = someArray;Это не будет фактически копировать
someArray, а вместо этого ссылаться на него, поэтому исходный массив изменяется.Вы можете использовать
Array.slice()для создания так называемой неглубокой копии массива.var funcArray = someArray.slice(0);Исходный массив будет неизменен, но каждый из его элементов будет по-прежнему ссылаться на соответствующие записи в исходном массиве. Для "глубокого клонирования" вам нужно сделать это рекурсивно; наиболее эффективный способ-это обсуждается в следующем вопросе:
Каков наиболее эффективный способ глубокого клонирования объекта в JavaScript?
кстати, я добавил
varПередfuncArray. Это делает его локальным для функции вместо того, чтобы быть глобальной переменной.
Сделайте копию массива, который вы можете использовать.
Простой способ сделать это с помощью
var clone = original.slice(0);
Переменная, указывающая на массив, является ссылкой на него. Когда вы передаете массив, вы копируете эту ссылку.
Вы можете сделать неглубокую копию с помощью
slice(). Если вы хотите получить копию полной глубины, то рекурсируйте в подобъектах, имея в виду предостережения При копировании некоторых объектов.
Общее решение было бы...
// 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);Это работает как для объектов, так и для массивов.
Очень эффективно, когда вам нужно глубокое клонирование или вы не знаете, что это за тип.Пример глубокого клонирования...
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Предупреждения
Использование синтаксического анализатора JSON для клонирования-не самый эффективный вариант!
Он не клонирует функции только поддерживаемые JSON типы данных
Не удается клонировать круговые ссылки
Если вам нужно сделать это с объектом, попробуйте этот причудливый трюк...
MY_NEW_OBJECT = JSON.parse(JSON.stringify(MY_OBJECT));
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]);Этот ответ был отредактирован. Сначала я предположил, что оператор
newобработал решение, но вскоре после этого признал эту ошибку. Вместо этого я решил использовать метод concat() для создания копии. Исходный ответ не показывал весь массив, поэтому ошибка была непреднамеренно скрыта. Новый результат, показанный ниже, докажет, что этот ответ работает, как и ожидалось.aArray: 0, 1, 2 aArrayCopy: A changed value., 1, 2
Comments