Копирование массива объектов в другой массив без ссылки на объект в javascript (Deep copy)
У меня есть сценарий, когда мне нужно скопировать массив объектов (Основной массив) в другой массив Temp, который не должен иметь ссылку на объект в основном, если я вношу какие-либо изменения в главный массив, который он не должен отражать в массиве Temp, так что я будет сохранять копию независимо.
Я использовал один из фрагментов кода из, который частично нравится, если я удаляю все объекты из массива Main, массив temp все еще удерживает значение, но когда я делаю некоторые изменения в основном массиве и нажмите кнопку отмены отмены iam все объекты из основного массива с использованием array.Removeall(); но модификация все еще существует в массиве Temp, поэтому это означает, что объект имеет ссылку.
clone: function (existingArray) {
var newObj = (existingArray instanceof Array) ? [] : {};
console.debug('newObj value is ' + newObj);
for (i in existingArray) {
console.debug('i value is' + i);
if (i == 'clone') continue;
console.debug('existingArray[i] value ' + existingArray[i]);
if (existingArray[i] && typeof existingArray[i] == "object") {
newObj[i] = this.clone(existingArray[i]);
} else {
console.debug('in else part ' + existingArray[i]);
newObj[i] = existingArray[i];
}
}
return newObj;
}
моя структура объекта похожа на
iam с использованием инфраструктуры нокаутов.
newObjectCreation = function (localIp, RemoteIp, areaId) {
this.localIP = ko.observable(localIp);
this.remoteIP = ko.observable(RemoteIp);
this.areaId = ko.observable(areaId);
};
template.ProtocolArray.push(new newObjectCreation('', '', '')); // to create default row
Пожалуйста, помогите мне в этом отношении.
Спасибо заранее.
Ответы
Ответ 1
Позвольте мне понять: вам не нужен только новый массив, но вы хотите создать новый экземпляр для всех объектов, присутствующих в самом массиве? Итак, если вы изменяете один из объектов в массиве temp, эти изменения не распространяются на главный массив?
Если это так, это зависит от значений, которые вы храните в основном массиве. Если эти объекты являются простыми объектами, и они могут быть сериализованы в JSON, то самый быстрый способ:
var tempArray = JSON.parse(JSON.stringify(mainArray));
Если у вас более сложные объекты (например, экземпляры, созданные некоторыми вашими конструкторами, узлами html и т.д.), вам нужен подход ad hoc.
Edit:
Если у вас нет методов на newObjectCreation
, вы можете использовать JSON
, однако конструктор не будет таким же. В противном случае вам нужно сделать копию вручную:
var tempArray = [];
for (var i = 0, item; item = mainArray[i++];) {
tempArray[i] = new newObjectCreation(item.localIP, item.remoteIP, item.areaId);
}
Ответ 2
Lodash может использоваться для глубокого копирования объектов _.cloneDeep (значение)
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// → false
Ответ 3
Значит, вам нужна глубокая копия без ссылки на объект? Конечно, используйте .slice()
.
Пример:
var mainArr = [],
tmpArr = []
tmpArr = mainArr.slice(0) // Shallow copy, no reference used.
PS: Я не думаю, что синтаксический анализ с двойным JSON показатель производительности.
Ответ 4
Для некоторых других людей с таким же вопросом. Вы также можете сделать это таким образом.
Используя новые функции es6, вы можете создать копию массива (без ссылки) и копию каждого объекта без одного уровня ссылок.
const copy = array.map(object => ({ ...object }))
Это намного функциональнее и идиоматичнее ИМХО
Примечание. Синтаксис Spread эффективно копируется на один уровень при копировании массива. Следовательно, он может быть неподходящим для копирования многомерных массивов, как показано в следующем примере (то же самое с Object.assign() и синтаксисом распространения).
Дополнительная информация: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
Так что, в основном, если ваши объекты не имеют объектов в качестве свойств. Этот синтаксис - это все, что вам нужно. К сожалению, в спецификации нет функции глубокого клонирования "из коробки", но вы всегда можете использовать библиотеку, если это то, что вам нужно
Предупреждение о совместимости браузера: я думаю, что сейчас это часть спецификации Ecma, но некоторые браузеры не имеют полной поддержки расширенной синтаксической струи. Но с помощью одного из популярных транспортеров вы будете в порядке
Ответ 5
Вы можете использовать Angular copy: angular.copy();
Ответ 6
Чтобы скопировать значения массива без копирования ссылки на массив, вы можете просто сделать:
let tempArray = [...mainArray];
Это рекомендуемое решение для AirBnb JS Style Guide: https://github.com/airbnb/javascript#arrays
Однако это не создаст новые ссылки для объектов внутри массива. Чтобы создать новую ссылку для массива и объектов внутри, вы можете сделать:
JSON.parse(JSON.stringify(mainArray));
Ответ 7
Используйте angular.copy
. Но не для всего массива (потому что он будет передавать элементы массива по ссылке), но итерируйте его и используйте angular.copy
для его членов.
var newArray = [];
for (var i = 0, item; item = mainArray[i];) {
newArray[i] = angular.copy(item);
i++;
}