Почему изменение массива в JavaScript влияет на копии массива?
я написал следующий JavaScript:
var myArray = ['a', 'b', 'c'];
var copyOfMyArray = myArray;
copyOfMyArray.splice(0, 1);
alert(myArray); // alerts ['b','c']
alert(copyOfMyArray); // alerts ['b','c']
var myNumber = 5;
var copyOfMyNumber = myNumber;
copyOfMyNumber = copyOfMyNumber - 1;
alert(myNumber); // alerts 5
alert(copyOfMyNumber); // alerts 4
этот код объявляет переменную myArray
и устанавливает его в значение массива. Затем он объявляет вторую переменную copyOfMyArray
С myArray
.
Он выполняет операцию на copyOfMyArray
и после предупреждения myArray
и copyOfMyArray
. Как-то, когда я выполняю операцию на copyOfMyArray
, похоже, что та же операция произведена на myArray
.
затем код делает то же самое с числовым значением: It объявляет переменную myNumber
и устанавливает его в числовое значение. Затем он объявляет вторую переменную copyOfMyNumber
С myNumber
. Он выполняет операцию на copyOfMyNumber
и после предупреждения myNumber
и copyOfMyNumber
. Здесь я получаю ожидаемое поведение: разные значения для myNumber
и copyOfMyNumber
.
в чем разница между массивом и числом в JavaScript, что кажется изменение массива изменяет значение копии массива, где как изменение числа не изменяется значение копии номера?
я предполагаю, что по какой-то причине массив ссылается на ссылку и число по значению, но почему? Как я могу знать, какое поведение ожидать с другими объектами?
13 ответов:
массив в JavaScript также является объект и переменные содержат только ссылка к объекту, а не к самому объекту. Таким образом, обе переменные имеют ссылку на тот же
Ну, единственный возможный ответ - и правильный - это то, что ты фактически не копирует массив. когда вы пишите
var copyOfArray = array;
вы назначаете ссылка в тот же массив в другую переменную. Они оба указывают на один и тот же объект, другими словами.
Так что все здесь сделали большую работу по объяснению почему это происходит - я просто хотел бросить строку и дать вам знать как я смог это исправить-довольно легко:
thingArray = ['first_thing', 'second_thing', 'third_thing'] function removeFirstThingAndPreserveArray(){ var copyOfThingArray = [...thingArray] copyOfThingArray.shift(); return copyOfThingArray; }
это с помощью ... синтаксис распространения.
Источник Синтаксиса Распространения
редактировать: Что касается почему из этого, и чтобы ответить на ваш вопрос:
в чем разница между массив и число в JavaScript, что кажется изменение массива изменяет значение копии массива, где как изменение числа не изменяет значение копии числа?
ответ заключается в том, что в JavaScript, массивы и объекты mutable, в то время как строки и числа и другие примитивы неизменяемые. Когда мы делаем задание, как:
var myArray = ['a', 'b', 'c']; var copyOfMyArray = myArray;
copyOfMyArray действительно просто ссылка на myArray, а не фактическая копия.
Я бы рекомендовал эту статью,что такое неизменяемые и изменяемые структуры данных?, чтобы копнуть глубже в тему.
клонирование объектов -
A
loop / array.push
дает аналогичный результатarray.slice(0)
илиarray.clone()
. Все значения передаются по ссылке, но так как большинство примитивных типов данных неизменяемые, последующие операции дают желаемый результат - "клон". Конечно, это не относится к объектам и массивам, которые позволяют изменять исходную ссылку (они являются изменяемыми типами).рассмотрим пример:
const originalArray = [1, 'a', false, {foor: 'bar'}] const newArray = []; originalArray.forEach((v, i) => { newArray.push(originalArray[i]); }); newArray[0] = newArray[0] + 1; newArray[1] = 'b'; newArray[2] = true; newArray[3] = Object.assign(newArray[3], {bar: 'foo'});
операции выполняются на индексах newArray все дают желаемый результат, кроме конечного (объекта), который, поскольку он копируется по ссылке, также мутирует исходный array[3].
https://jsfiddle.net/7ajz2m6w/
отметим, что
array.slice(0)
and array.clone()
страдает от этого же ограничения.один из способов решить эту проблему-эффективно клонировать объект во время нажатия последовательность:
originalArray.forEach((v, i) => { const val = (typeof v === 'object') ? Object.assign({}, v) : v; newArray.push(val); });
https://jsfiddle.net/e5hmnjp0/
ура
в JS оператор " = " копирует указатель в область памяти массива. Если вы хотите скопировать массив в другой, вы должны использовать функцию клонирования.
для целых чисел отличается тем, что они являются примитивным типом.
S.
создайте фильтр исходного массива в arrayCopy. Так что изменения в новом массиве не повлияют на исходный массив.
var myArray = ['a', 'b', 'c']; var arrayCopy = myArray.filter(function(f){return f;}) arrayCopy.splice(0, 1); alert(myArray); // alerts ['a','b','c'] alert(arrayCopy); // alerts ['b','c']
надеюсь, что это помогает.
у вас нет никаких копий.
У вас есть несколько переменных, содержащих один и тот же массив.аналогично, у вас есть несколько переменных, имеющих ряд.
когда вы пишите
copyOfMyNumber = ...
, вы вводите новое число в переменную.
Это как писатьcopyOfMyArray = ...
.когда вы пишите
copyOfMyArray.splice
, ты изменение исходного массива.
Это невозможно с числами, потому что числа неизменны и не могут быть изменено,
вы можете добавить некоторую обработку ошибок в зависимости от ваших случаев и использовать что-то похожее на следующую функцию для решения проблемы. Пожалуйста, прокомментируйте любые ошибки / проблемы / идеи эффективности.
function CopyAnArray (ari1) { var mxx4 = []; for (var i=0;i<ari1.length;i++) { var nads2 = []; for (var j=0;j<ari1[0].length;j++) { nads2.push(ari1[i][j]); } mxx4.push(nads2); } return mxx4; }
другим подходом для копирования массива во временную переменную может быть типизация/изменение массива в строку, а затем его извлечение.
например.
var a = [1,2,3]; typeof(a) (this will give "object") var b = JSON.stringify(a); typeof(b) (this will give "string"); b = JSON.parse(b); typeOf(b) (this will give "object")
и теперь chnage в значении b не будет отражаться на a
массив или объект в javascript всегда содержит одну и ту же ссылку, если вы не клонируете или не копируете. Вот пример:
http://plnkr.co/edit/Bqvsiddke27w9nLwYhcl?p=preview
// for showing that objects in javascript shares the same reference var obj = { "name": "a" } var arr = []; //we push the same object arr.push(obj); arr.push(obj); //if we change the value for one object arr[0].name = "b"; //the other object also changes alert(arr[1].name);
для клонирования объекта, мы можем использовать .clone () в jquery и angular.copy (), эти функции создадут новый объект с другой ссылкой. Если вы знаете больше функций для этого, пожалуйста, скажите мне, спасибо!
Я считаю, это самый простой способ сделать глубокий клон объекта или массив:
const objectThatIWantToClone = { foo: 'bar'}; const clone = JSON.parse(JSON.stringify(objectThatIWantToClone));
по его строкового представления мы делаем копию, которая является неизменяемым, которые затем можно преобразовать обратно в JSON.
ответ тут
var myArray = ['a', 'b', 'c']; var copyOfMyArray = myArray.slice();
в принципе, операция slice () клонирует массив и возвращает мелкую копию.
copyOfMyArray.splice(0, 1); alert(myArray); // alerts ['a', 'b', 'c'] alert(copyOfMyArray); // alerts ['b','c']
четкую документацию можно найти по следующей ссылке: массив.прототип.slice ()