Я написал следующий код 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
.
Затем код делает то же самое с числовым значением: он объявляет переменную myNumber
и устанавливает для нее числовое значение. Затем он объявляет вторую переменную copyOfMyNumber
и устанавливает для нее значение myNumber
. Он выполняет операцию, copyOfMyNumber
а затем предупреждает оба myNumber
и copyOfMyNumber
. Здесь я получаю ожидаемое поведение: разные значения для myNumber
и copyOfMyNumber
.
В чем разница между массивом и числом в JavaScript в том, что кажется, что изменение массива изменяет значение копии массива, тогда как изменение числа не меняет значение копии числа?
Я предполагаю, что почему-то на массив ссылаются по ссылке, а число по значению, но почему? Как я могу узнать, какого поведения ожидать от других объектов?
источник
myArray.slice(0);
непосредственно в этом контексте?Что ж, единственный возможный ответ - и правильный - это то, что вы на самом деле не копируете массив. Когда ты пишешь
var copyOfArray = array;
вы назначаете ссылку на тот же массив другой переменной. Другими словами, они оба указывают на один и тот же объект.
источник
5
всегда равны.Итак, все здесь хорошо поработали, объяснив, почему это происходит - я просто хотел сказать пару слов и сообщить, как мне удалось это исправить - довольно легко:
thingArray = ['first_thing', 'second_thing', 'third_thing'] function removeFirstThingAndPreserveArray(){ var copyOfThingArray = [...thingArray] copyOfThingArray.shift(); return copyOfThingArray; }
Это использует синтаксис ... распространения.
Источник синтаксиса распространения
РЕДАКТИРОВАТЬ: Относительно того, почему это, и чтобы ответить на ваш вопрос:
Ответ заключается в том, что в JavaScript массивы и объекты изменяемы , тогда как строки, числа и другие примитивы неизменны . Когда мы выполняем такое задание, как:
copyOfMyArray на самом деле просто ссылка на myArray, а не фактическая копия.
Я бы порекомендовал эту статью, Что такое неизменяемые и изменяемые структуры данных? , чтобы глубже вникнуть в тему.
Глоссарий MDN: изменчивый
источник
Клонирование объектов -
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, дают желаемый результат, за исключением final (object), который, поскольку он копируется по ссылке, также изменяет originalArray [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 оператор "=" копирует указатель в область памяти массива. Если вы хотите скопировать массив в другой, вы должны использовать функцию Clone.
Для целых чисел все по-другому, потому что они примитивный тип.
С.
источник
Все копируется по ссылке, кроме примитивных типов данных (строки и числа IIRC).
источник
У вас нет копий.
У вас есть несколько переменных, содержащих один и тот же массив.
Точно так же у вас есть несколько переменных, содержащих одно и то же число.
Когда вы пишете
copyOfMyNumber = ...
, вы помещаете в переменную новое число.Это как писать
copyOfMyArray = ...
.Когда вы пишете
copyOfMyArray.splice
, вы изменяете исходный массив .Это невозможно с числами, потому что числа неизменяемы и не могут быть изменены.
источник
Создайте фильтр исходного массива в 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']
Надеюсь, поможет.
источник
Проблема с неглубокой копией заключается в том, что все объекты не клонируются, вместо этого она получает ссылку. Таким образом, array.slice (0) будет нормально работать только с литеральным массивом, но не будет выполнять неглубокую копию с массивом объектов. В этом случае один из способов ...
var firstArray = [{name: 'foo', id: 121}, {name: 'zoo', id: 321}]; var clonedArray = firstArray.map((_arrayElement) => Object.assign({}, _arrayElement)); console.log(clonedArray); // [{name: 'foo', id: 121}, {name: 'zoo', id: 321}] // shallow copy
источник
Вы можете добавить некоторую обработку ошибок в зависимости от ваших случаев и использовать что-то похожее на следующую функцию для решения проблемы. Прокомментируйте любые ошибки / проблемы / идеи по эффективности.
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; }
источник
Массив или объект в 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 (), эти функции создадут новый объект с другой ссылкой. Если вам известны другие функции для этого, сообщите мне, спасибо!
источник