... где каждый объект также имеет ссылки на другие объекты в том же массиве?
Когда я впервые столкнулся с этой проблемой, я просто
var clonedNodesArray = nodesArray.clone()
будет существовать и искать информацию о том, как клонировать объекты в JavaScript. Я нашел вопрос о StackOverflow (на который ответил тот же @JohnResig), и он указал, что с jQuery вы можете сделать
var clonedNodesArray = jQuery.extend({}, nodesArray);
клонировать объект. Я попробовал это, хотя, это только копирует ссылки на объекты в массиве. Так что если я
nodesArray[0].value = "red"
clonedNodesArray[0].value = "green"
значение обоих nodeArray [0] и clonedNodesArray [0] окажется «зеленым». Потом я попробовал
var clonedNodesArray = jQuery.extend(true, {}, nodesArray);
который глубоко копирует объект, но я получил сообщения « слишком много рекурсии » и « переполнение стека управления » от Firebug и Opera Dragonfly соответственно.
Как бы вы это сделали? Это что-то, что даже не следует делать? Есть ли способ повторного использования в Javascript?
источник
Пока ваши объекты содержат JSON-сериализуемый контент (без функций, без
Number.POSITIVE_INFINITY
и т. Д.), Не нужно никаких циклов для клонирования массивов или объектов. Здесь чисто ванильное однострочное решение.Подводя итог приведенным ниже комментариям, основное преимущество этого подхода заключается в том, что он также клонирует содержимое массива, а не только сам массив. Основными недостатками являются ограничение на работу только с сериализуемым JSON-контентом и его производительность (что значительно хуже, чем на
slice
основе подхода).источник
null
иundefined
будут проблемы, поскольку JSON их не поддерживает). Кроме того, это значительно менее эффективная операция, чем таold_array.slice(0);
, которая должна работать как лучше, так и быстрее.Я решил клонирование массива объектов с Object.assign
или даже короче с синтаксисом распространения
источник
{}
наnew Dinosaur()
.Если все, что вам нужно, это мелкая копия, то действительно простой способ:
источник
0
, вы все равно можете просто позвонить.slice()
хотя бы в chromeslice
будет новым массивом, но будет содержать ссылки на исходные объекты массива.Лучший и самый современный способ сделать этот клон заключается в следующем:
Использование
...
оператора распространения ES6.Вот самый простой пример:
Таким образом мы распределяем массив по отдельным значениям и помещаем его в новый массив с помощью оператора [].
Вот более длинный пример, который показывает различные способы его работы:
источник
Это работает для меня:
И если вам нужна глубокая копия объектов в массиве:
источник
источник
JSON.parse(JSON.stringify(origArray));
JSON.parse(JSON.stringify(origArray));
безусловно, самое простое решение.Map создаст новый массив из старого (без ссылки на старый), и внутри карты вы создадите новый объект, перебираете свойства (ключи) и присваиваете значения из старого объекта Array для соответствующих свойств новому объекту.
Это создаст точно такой же массив объектов.
источник
У меня может быть простой способ сделать это, не выполняя мучительную рекурсию и не зная всех мелких деталей рассматриваемого объекта. Используя jQuery, просто преобразуйте ваш объект в JSON с помощью jQuery
$.toJSON(myObjectArray)
, затем возьмите строку JSON и оцените ее обратно в объект. BAM! Готово и готово! Задача решена. :)источник
eval
.eval()
вообще. Это риск для безопасности.Я отвечаю на этот вопрос, потому что, кажется, нет простого и явного решения проблемы «клонирования массива объектов в Javascript»:
Это решение перебирает значения массива, затем перебирает ключи объекта, сохраняя последние в новом объекте, а затем помещая этот новый объект в новый массив.
Видеть jsfiddle . Примечание: просто
.slice()
или[].concat()
недостаточно для объектов в массиве.источник
Расширение JQuery работает нормально, вам просто нужно указать, что вы клонируете массив, а не объект ( обратите внимание на [] вместо {} в качестве параметра для метода расширения ):
источник
Этот метод очень прост, и вы можете изменить свой клон без изменения исходного массива.
источник
[...oldArray]
иoldArray.slice(0)
делает поверхностную копию глубиной в один уровень. Так что это супер полезно, но не полный клон.lodash.clonedeep
npmКак отметил Дэниел Лью, у циклических графов есть некоторые проблемы. Если бы у меня была эта проблема, я бы добавил
clone()
методы к проблемным объектам, либо запомнил, какие объекты я уже скопировал.Я бы сделал это с переменной,
copyCount
которая увеличивается на 1 каждый раз, когда вы копируете свой код. Объект, который имеет более низкий,copyCount
чем текущий процесс копирования, копируется. Если нет, на копию, которая уже существует, следует ссылаться. Это делает необходимым ссылку с оригинала на его копию.Есть еще одна проблема: память. Если у вас есть эта ссылка от одного объекта к другому, вероятно, браузер не сможет освободить эти объекты, так как на них всегда есть ссылки откуда-то. Вам нужно будет сделать второй проход, где вы установите все ссылки на копии в Null. (Если вы сделаете это, вам не нужно иметь,
copyCount
ноisCopied
будет достаточно логического значения , так как вы можете сбросить значение во втором проходе.)источник
Array.slice может использоваться для копирования массива или его части. Http://www.devguru.com/Technologies/Ecmascript/Quickref/Slice.html Это будет работать со строками и числами .. - изменение строки в один массив не будет влиять на другой - но объекты по-прежнему просто копируются по ссылке, поэтому изменения ссылочных объектов в одном массиве будут влиять на другой массив.
Вот пример менеджера отмены JavaScript, который может быть полезен для этого: http://www.ridgway.co.za/archive/2007/11/07/simple-javascript-undo-manager-for-dtos.aspx
источник
Мой подход:
дает мне хороший, чистый, глубокий клон исходного массива - ни один из объектов не ссылается на исходный :-)
источник
У lodash есть
cloneDeep
функция для этих целей:источник
Если вы хотите реализовать глубокое клонирование, используйте JSON.parse (JSON.stringify (ваш {} или []))
источник
забудьте eval () (это наиболее неправильно используемая функция JS и замедляет код) и slice (0) (работает только для простых типов данных)
Это лучшее решение для меня:
источник
Я был довольно разочарован этой проблемой. Очевидно, проблема возникает, когда вы отправляете универсальный массив в метод $ .extend. Итак, чтобы исправить это, я добавил небольшую проверку, и она отлично работает с универсальными массивами, массивами jQuery и любыми объектами.
Вызвать используя:
источник
Это глубоко копирует массивы, объекты, нулевые и другие скалярные значения, а также глубоко копирует любые свойства не встроенных функций (что довольно редко, но возможно). (Для эффективности мы не пытаемся копировать нечисловые свойства для массивов.)
источник
Я использую новый метод ECMAScript 6 Object.assign :
первый аргумент этого метода - массив, который нужно обновить, мы передаем пустой объект, потому что хотим получить новый объект.
мы также можем использовать этот синтаксис, который такой же, но более короткий:
источник
Мы можем изобрести простой рекурсивный метод Array для клонирования многомерных массивов. В то время как объекты во вложенных массивах сохраняют свои ссылки на соответствующие объекты в исходном массиве, массивы не будут.
источник
В JavaScript копирование массивов и объектов изменяет исходные значения, поэтому Deep Copy является решением для этого.
Глубокая копия означает на самом деле создание нового массива и копирование значений, поскольку все, что происходит с ним, никогда не повлияет на исходный.
JSON.parse
иJSON.stringify
это лучший и простой способ глубокого копирования. ВJSON.stringify()
метод преобразует значение JavaScript в JSON string.TheJSON.parse()
метод анализирует строку JSON, конструируя значение JavaScript или объект , описанный в строке.// Глубокий клон
Для более подробной информации: читайте здесь
источник
с помощью jQuery:
источник
Следующий код выполнит рекурсивно глубокое копирование объектов и массива :
Источник
источник
arguments.callee
недоступен в строгом режиме и имеет проблемы с производительностью в противном случае.Несколько элегантных способов глубокого клонирования в javascript
https://mootools.net/core/docs/1.6.0/Types/Object
https://scotch.io/bar-talk/copying-objects-in-javascript
1) Ванильный метод Javascript для клонирования объектов
2) Умное использование библиотеки JSON для глубоко клонированных объектов.
3) Использование функции $ .extend () в jQuery
4) Использование функции Mootools clone () для клонирования объектов
источник
Я думаю, что удалось написать общий метод глубокого клонирования любой структуры JavaScript, в основном с использованием,
Object.create
который поддерживается во всех современных браузерах. Код выглядит так:источник
Object.create
будет рассматриватьсяitem
как прототип объекта, но это отличается от клонирования. Еслиitem
это изменение, изменения будут отражены в его «клоне» и наоборот. Этот подход не работает.Также для клонирования объектов я собирался предложить ECMAScript 6
reduce()
:Но, честно говоря, мне больше нравится ответ @dinodsaurus. Я просто выкладываю эту версию здесь как еще один вариант, но лично я буду использовать,
map()
как предложено @dinodsaurus.источник
В зависимости от того, есть ли у вас Underscore или Babel, здесь есть эталон другого способа глубокого клонирования массива.
https://jsperf.com/object-rest-spread-vs-clone/2
Похоже, Babel самый быстрый.
источник
источник