Я озадачен, почему этот следующий бит кода вернет мутации как локального, так и глобального массива:
var globalarray = [1,2,3];
function test(){
let localarray = globalarray;
localarray.push(4);
console.log(localarray);
console.log(globalarray);
}
setInterval(test, 2000);
Возвращает:
[1,2,3,4] for both
Мое впечатление было то, что localarray
будет копией globalarray
. Я увидел еще один ответ, который сказал, чтобы сделать копию массива, которую нужно использовать .slice().reverse()
, который кажется обходным путем. Почему он не просто создает новую локальную копию? Есть ли простой и эффективный способ создания локальной копии глобального массива? В противном случае кажется, что создание нескольких мутаций для глобального массива ужасно для производительности.
Причина этого в вашем коде заключается в том, что вы просто говорите своей test
функции, globalarray
на globalarray
с помощью оператора =
. Это связано с тем, что в JavaScript назначения переменных не по своей сути "копируют" объекты в новые переменные; это может показаться запутанным, поэтому просто подумайте об операторе =
как знаке, указывающем ваш код на местоположение объекта.
Единственный раз, когда оператор =
создает новые копии, - это когда вы работаете с примитивными типами. В таких случаях вы не можете по своей сути изменить то, что эти объекты, поэтому =
достаточно, чтобы сделать копию, как вы ожидали.
Причина .slice().reverse()
заключается в том, чтобы обойти проблему, которую вы видите. Другой способ, которым вы могли бы это сделать, - использовать let localarray = globalarray.map(e => e)
или как это было предложено, используя let localarray = [...globalarray]
. Оператор .map
принимает функцию, данную ему как первый аргумент, и применяет ее к каждому элементу, а затем сохраняет результат в другом массиве в другом месте, которое не совпадает с globalarray
.
Имейте в виду, что эти методы и любые другие, которые могут быть предложены вам, являются сокращенными способами
let localarray = new Array(globalarray.length);
for (let i = 0; i < globalarray.length; i++) {
localarray[i] = globalarray[i];
}
// localarray can now be freely modified because it does not point to the same array as globalarray
Также имейте в виду, что если вам нужно также создать копии элементов внутри массивов, вам придется использовать более полный код копирования. Есть библиотеки, которые могут выполнять такое тяжелое копирование, если вам это действительно нужно.
Простой способ клонирования массива - это просто
let localarray = globalarray.slice();
Я делаю это по-другому для глубокого клонирования:
clone: function() {
var clone = undefined;
var instance = this;
if ( XScript.is.xobject(instance) ) {
clone = {};
for ( var prop in instance ) {
if ( instance.hasOwnProperty(prop) ) {
var p = instance[prop];
if ( XScript.is.xobject(p) ) p = p.clone();
clone[prop] = p;
}//END IF this
}//END FOR prop
return clone;
}//END IF xobject
if ( XScript.is.xarray(instance) ) {
clone = instance.slice(0);
return clone;
}
return clone;
}//END FUNCTION clone
Этот клон потребует, чтобы вы прикрепляли объект клона к прототипу объекта и проверяли, есть ли его массив, объект или другое. Я не изменяю функцию, чтобы соответствовать всем вашим потребностям, потому что нужно немного научиться ее менять и что делать, а не копировать макароны. Плюс это просто пример.
В JavaScript (как и во многих других языках) объекты передаются по ссылке. Массивы также передаются по ссылке (потому что массив фактически является типом объекта). Поэтому, когда вы говорите: let localarrray = globalarray
, вы на самом деле устанавливаете localarray
указателю, который разрешает globalarray
.
Существует несколько стратегий получения подлинной копии. Если вы пытаетесь получить новую копию исходного массива, функция прототипа массива .map()
является одним из наиболее целенаправленных инструментов для задания. Это будет выглядеть так:
let localarray = globalarray.map(element => element);
let localarray = globalarray
не будет создавать новый массив и присваивать globalarray. вы можете использовать оператор распространенияlet localarray = [...globalarray]
но имейте в виду, что оператор распространения делает только поверхностное копирование.