Как вы клонируете массив объектов в Javascript?

422

... где каждый объект также имеет ссылки на другие объекты в том же массиве?

Когда я впервые столкнулся с этой проблемой, я просто

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?

wallyqs
источник

Ответы:

106

Проблема с вашей мелкой копией в том, что не все объекты клонированы. Хотя ссылки на каждый объект уникальны в каждом массиве, после того, как вы в конечном итоге ухватитесь за него, вы имеете дело с тем же объектом, что и раньше. Нет ничего плохого в том, как вы его клонировали ... тот же результат будет получен при использовании Array.slice ().

Причина, по которой у вашей глубокой копии возникают проблемы, заключается в том, что вы заканчиваете круговыми ссылками на объекты. Глубокий будет идти как можно глубже, и если у вас есть круг, он будет продолжаться бесконечно, пока браузер не потеряет сознание.

Если структура данных не может быть представлена ​​в виде ориентированного ациклического графа, то я не уверен, что вы сможете найти универсальный метод для глубокого клонирования. Циклические графы предоставляют множество хитрых угловых случаев, и, поскольку это не обычная операция, я сомневаюсь, что кто-то написал полное решение (если это вообще возможно - это может быть не так! Но у меня нет времени пытаться написать строгое доказательство сейчас). Я нашел несколько хороших комментариев по этому вопросу на этой странице .

Если вам нужна глубокая копия массива объектов с циклическими ссылками, я думаю, вам придется написать собственный метод для обработки вашей специализированной структуры данных, такой, чтобы это был многопроходный клон:

  1. В первом раунде создайте клон всех объектов, которые не ссылаются на другие объекты в массиве. Следите за происхождением каждого объекта.
  2. Во втором раунде свяжите объекты вместе.
Дэн Лью
источник
1
Исправлена ​​ссылка для ответа @PatrickdeKleijn: web.archive.org/web/20140222022056/http://my.opera.com/…
Майк Шиндель,
532

Пока ваши объекты содержат JSON-сериализуемый контент (без функций, без Number.POSITIVE_INFINITYи т. Д.), Не нужно никаких циклов для клонирования массивов или объектов. Здесь чисто ванильное однострочное решение.

var clonedArray = JSON.parse(JSON.stringify(nodesArray))

Подводя итог приведенным ниже комментариям, основное преимущество этого подхода заключается в том, что он также клонирует содержимое массива, а не только сам массив. Основными недостатками являются ограничение на работу только с сериализуемым JSON-контентом и его производительность (что значительно хуже, чем на sliceоснове подхода).

Владимир Харлампиди
источник
118
Это может работать для данных JSON, но если ваш массив содержит какие-либо функции или экземпляры объектов, у которых есть методы, попрощайтесь с ними.
sp0rkyd0rky
12
будьте осторожны, если у вас есть массив, который содержит значение Infinity. Это значение теряется (потом становится нулевым). ( jsfiddle.net/klickagent/ehm4bd3s )
klickagent.ch
13
Это просто плохой подход, если только ваш массив не содержит только примитивы и / или объекты, которые сами содержат только строковые / числовые / логические примитивы (даже nullи undefinedбудут проблемы, поскольку JSON их не поддерживает). Кроме того, это значительно менее эффективная операция, чем та old_array.slice(0);, которая должна работать как лучше, так и быстрее.
XML
2
если объект массива имеет DateTime, то строка будет возвращена вместо DateTime! новая дата! == JSON.parse (JSON.stringify (новая дата))
MarkosyanArtur
2
Ключевая строка в вопросе ОП, которую этот ответ выше полностью игнорирует: ... где каждый объект также имеет ссылки на другие объекты в том же массиве?
XML
288

Я решил клонирование массива объектов с Object.assign

const newArray = myArray.map(a => Object.assign({}, a));

или даже короче с синтаксисом распространения

const newArray = myArray.map(a => ({...a}));
dinodsaurus
источник
15
Но если myArray содержит кучу динозавров, newArray содержит кучу объектов. Это хромое, ты не согласен?
Мэтью Джеймс Дэвис,
3
лучший подход, так как он поддерживает функции объектов живыми, а затем теряет их с помощью JSON.parse (JSON.stringify (nodeArray))
scipper
14
@ MatthewJamesDavis вы можете решить эту проблему, заменив {}на new Dinosaur().
Агаргара
5
мелкая копия не глубокая копия
султан Аслам
1
Это прекрасно работает для массива объектов, если эти объекты содержат только примитивные свойства ... это то, что мне нужно, спасибо
mojave
154

Если все, что вам нужно, это мелкая копия, то действительно простой способ:

new_array = old_array.slice(0);
Leopd
источник
6
Я не думаю, что вы должны пройти 0, вы все равно можете просто позвонить .slice()хотя бы в chrome
slf
112
Это на самом деле не работает, правда? Я имею в виду, это не ответ на вопрос, как клонировать массив объектов. Это решение для клонирования простого массива.
Боздоз
35
На самом деле это не будет работать для массива объектов. Возвращенный массив sliceбудет новым массивом, но будет содержать ссылки на исходные объекты массива.
Серхио А.
4
Это будет работать только для «обобщенных» типов int, string и т. Д., Но не для массива объектов.
Стефан Мичев
5
для массива объектов это на самом деле не клонируется, обновление до new_array также обновит old_array.
Анас
44

Лучший и самый современный способ сделать этот клон заключается в следующем:

Использование ...оператора распространения ES6.

Вот самый простой пример:

var clonedObjArray = [...oldObjArray];

Таким образом мы распределяем массив по отдельным значениям и помещаем его в новый массив с помощью оператора [].

Вот более длинный пример, который показывает различные способы его работы:

let objArray = [ {a:1} , {b:2} ];

let refArray = objArray; // this will just point to the objArray
let clonedArray = [...objArray]; // will clone the array

console.log( "before:" );
console.log( "obj array" , objArray );
console.log( "ref array" , refArray );
console.log( "cloned array" , clonedArray );

objArray[0] = {c:3};

console.log( "after:" );
console.log( "obj array" , objArray ); // [ {c:3} , {b:2} ]
console.log( "ref array" , refArray ); // [ {c:3} , {b:2} ]
console.log( "cloned array" , clonedArray ); // [ {a:1} , {b:2} ]

MennyMez
источник
2
Хороший современный ответ, который не будет работать со старыми браузерами (например, IE 11)
Jealie
1
@Jealie Я собираюсь предположить, что KingpinEX нацелен на этот ответ для людей, которые переносят es6 во что-то более универсальное с Babel или чем-то еще.
ruffin
61
Это просто копирует массив, а не каждый объект в массиве.
Тойво Савен
31
Чтобы понять, что сказал @ ToivoSäwén, это не приведет к глубокому копированию объектов в массиве. Он по-прежнему будет ссылаться на исходные объекты, поэтому, если вы измените их, это также повлияет на исходный массив.
Джоэл
3
Работает только для примитивов. Попробуйте это: objArray [0] .a = 3; и вы увидите, что ссылка на объект остается неизменной в clonedArray.
Серхио Корреа,
25

Это работает для меня:

var clonedArray = $.map(originalArray, function (obj) {
                      return $.extend({}, obj);
                  });

И если вам нужна глубокая копия объектов в массиве:

var clonedArray = $.map(originalArray, function (obj) {
                      return $.extend(true, {}, obj);
                  });
viliks
источник
1
Похоже, это будет работать. Я пытаюсь избежать широкого использования jQuery, поэтому я не буду использовать его в моей ситуации, но цикл for и for ... in сработает.
Боздоз
19
$.evalJSON($.toJSON(origArray));
elsereturn
источник
2
Вам нужно будет использовать плагин jquery json, чтобы использовать этот code.google.com/p/jquery-json
wmitchell
32
Без JQ (отлично в современных браузерах):JSON.parse(JSON.stringify(origArray));
forresto
Я нашел этот комментарий полезным. В моей реализации мне нужно было сделать копию массива объектов, к которым были применены наблюдаемые свойства KnockoutJS. Копия нуждалась только в значениях, а не в наблюдаемости. Чтобы сделать копию JUST значений, я использовал JSON.parse (ko.toJSON (origArray)) ИЛИ ko.utils.parseJson (ko.toJSON (origArray)). Просто мои 2 цента и спасибо, что помогли мне прийти к моему решению.
Wavedrop
6
JSON.parse(JSON.stringify(origArray));безусловно, самое простое решение.
Йорк
JQuery часто не нужен. youmightnotneedjquery.com
ADJenks
9

Map создаст новый массив из старого (без ссылки на старый), и внутри карты вы создадите новый объект, перебираете свойства (ключи) и присваиваете значения из старого объекта Array для соответствующих свойств новому объекту.

Это создаст точно такой же массив объектов.

let newArray = oldArray.map(a => {
               let newObject = {};
               Object.keys(a).forEach(propertyKey => {
                    newObject[propertyKey] = a[propertyKey];
               });
               return newObject ;
});
eomeroff
источник
8

У меня может быть простой способ сделать это, не выполняя мучительную рекурсию и не зная всех мелких деталей рассматриваемого объекта. Используя jQuery, просто преобразуйте ваш объект в JSON с помощью jQuery $.toJSON(myObjectArray), затем возьмите строку JSON и оцените ее обратно в объект. BAM! Готово и готово! Задача решена. :)

var oldObjArray = [{ Something: 'blah', Cool: true }];
var newObjArray = eval($.toJSON(oldObjArray));
Джордж
источник
21
Некоторые современные браузеры имеют встроенный метод JSON, поэтому вы можете сделать это: JSON.parse (JSON.stringify (MY_ARRAY)), который должен быть быстрее. Хорошее предложение.
Николас Р
1
И если они не используют json2 , нет eval.
kamranicus
Это ужасная производительность, но, к сожалению, это лучший ответ, который я видел: /
Дид Сильва
Не оценивайте ничего с данными пользователя. Желательно никогда не использовать eval()вообще. Это риск для безопасности.
ADJenks
8

Я отвечаю на этот вопрос, потому что, кажется, нет простого и явного решения проблемы «клонирования массива объектов в Javascript»:

function deepCopy (arr) {
    var out = [];
    for (var i = 0, len = arr.length; i < len; i++) {
        var item = arr[i];
        var obj = {};
        for (var k in item) {
            obj[k] = item[k];
        }
        out.push(obj);
    }
    return out;
}

// test case

var original = [
    {'a' : 1},
    {'b' : 2}
    ];

var copy = deepCopy(original);

// change value in copy
copy[0]['a'] = 'not 1';

// original[0]['a'] still equals 1

Это решение перебирает значения массива, затем перебирает ключи объекта, сохраняя последние в новом объекте, а затем помещая этот новый объект в новый массив.

Видеть jsfiddle . Примечание: просто .slice()или [].concat()недостаточно для объектов в массиве.

bozdoz
источник
спасибо за ответ, но вы должны были подчеркнуть недостатки ответа. Это не работает, когда у объектов есть объекты в этом .. правильно?
Суровый
это создаст мелкую копию. не глубоко
султан Аслам
вам нужно куда-нибудь добавить рекурсию
DGoiko
6

Расширение JQuery работает нормально, вам просто нужно указать, что вы клонируете массив, а не объект ( обратите внимание на [] вместо {} в качестве параметра для метода расширения ):

var clonedNodesArray = jQuery.extend([], nodesArray);
Stef
источник
2
Хм, если вы отрицаете это, можете ли вы добавить комментарий о том, почему вы это делаете? Или вы можете сначала попробовать код и посмотреть, работает ли он или нет? Спасибо;)
Stef
1
После изменения объекта в первом массиве объект во втором массиве изменяется, поэтому это не нормально.
Spikolynn
6

Этот метод очень прост, и вы можете изменить свой клон без изменения исходного массива.

// Original Array
let array = [{name: 'Rafael'}, {name: 'Matheus'}];

// Cloning Array
let clone = array.map(a => {return {...a}})

// Editing the cloned array
clone[1].name = 'Carlos';


console.log('array', array)
// [{name: 'Rafael'}, {name: 'Matheus'}]

console.log('clone', clone)
// [{name: 'Rafael'}, {name: 'Carlos'}]

Рафаэль Грили
источник
1
Это делает поверхностную копию глубиной в два уровня, тогда как [...oldArray]и oldArray.slice(0)делает поверхностную копию глубиной в один уровень. Так что это супер полезно, но не полный клон.
Бен Уилер
истинный глубокий клон можно сделать с помощью lodash.clonedeepnpm
revelt
5

Как отметил Дэниел Лью, у циклических графов есть некоторые проблемы. Если бы у меня была эта проблема, я бы добавилclone() методы к проблемным объектам, либо запомнил, какие объекты я уже скопировал.

Я бы сделал это с переменной, copyCountкоторая увеличивается на 1 каждый раз, когда вы копируете свой код. Объект, который имеет более низкий, copyCountчем текущий процесс копирования, копируется. Если нет, на копию, которая уже существует, следует ссылаться. Это делает необходимым ссылку с оригинала на его копию.

Есть еще одна проблема: память. Если у вас есть эта ссылка от одного объекта к другому, вероятно, браузер не сможет освободить эти объекты, так как на них всегда есть ссылки откуда-то. Вам нужно будет сделать второй проход, где вы установите все ссылки на копии в Null. (Если вы сделаете это, вам не нужно иметь, copyCountно isCopiedбудет достаточно логического значения , так как вы можете сбросить значение во втором проходе.)

Георг Шолли
источник
4

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

Markt
источник
Я знаю. Причина, по которой я хотел реализовать это, заключается в том, что я пытаюсь решить проблему CSP с помощью обратного отслеживания. Я подумал, что одним из способов реализации обратного отслеживания может быть как «создание снимков» состояния назначения переменных путем ... клонирования таких снимков в стек.
Wallyqs
... и это может быть очень плохой идеей.
Wallyqs
У этого подхода могут быть другие сложности с синхронизацией :). Откуда вы знаете, что массив не изменяется во время создания снимка?
Markt
Добавлена ​​ссылка на статью, где автор реализовал простой менеджер отмены, используя javascript ..
markt
4

Мой подход:

var temp = { arr : originalArray };
var obj = $.extend(true, {}, temp);
return obj.arr;

дает мне хороший, чистый, глубокий клон исходного массива - ни один из объектов не ссылается на исходный :-)

туманностей
источник
Это лучшее решение с использованием jquery. коротко и сладко.
Джон Хенкель
1
Я провел тест производительности, и это решение примерно в 2 раза быстрее, чем решение JSON.stringify.
meehocz
4

У lodash есть cloneDeepфункция для этих целей:

var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
DicBrus
источник
4

Если вы хотите реализовать глубокое клонирование, используйте JSON.parse (JSON.stringify (ваш {} или []))

const myObj ={
    a:1,
    b:2,
    b:3
}

const deepClone=JSON.parse(JSON.stringify(myObj));
deepClone.a =12;
console.log("deepClone-----"+myObj.a);
const withOutDeepClone=myObj;
withOutDeepClone.a =12;
console.log("withOutDeepClone----"+myObj.a);

судхир нунна
источник
3

забудьте eval () (это наиболее неправильно используемая функция JS и замедляет код) и slice (0) (работает только для простых типов данных)

Это лучшее решение для меня:

Object.prototype.clone = function() {
  var myObj = (this instanceof Array) ? [] : {};
  for (i in this) {
    if (i != 'clone') {
        if (this[i] && typeof this[i] == "object") {
          myObj[i] = this[i].clone();
        } else 
            myObj[i] = this[i];
        } 
    }
  return myObj;
};
krupar
источник
3

Я был довольно разочарован этой проблемой. Очевидно, проблема возникает, когда вы отправляете универсальный массив в метод $ .extend. Итак, чтобы исправить это, я добавил небольшую проверку, и она отлично работает с универсальными массивами, массивами jQuery и любыми объектами.

jQuery.extend({
    deepclone: function(objThing) {
        // return jQuery.extend(true, {}, objThing);
        /// Fix for arrays, without this, arrays passed in are returned as OBJECTS! WTF?!?!
        if ( jQuery.isArray(objThing) ) {
            return jQuery.makeArray( jQuery.deepclone($(objThing)) );
        }
        return jQuery.extend(true, {}, objThing);
    },
});

Вызвать используя:

var arrNewArrayClone = jQuery.deepclone(arrOriginalArray);
// Or more simply/commonly
var arrNewArrayClone = $.deepclone(arrOriginalArray);
Браке
источник
deepclone? Я использую jquery-1.9.1, и он не поддерживает этот метод. Это метод более современной версии?
user5260143
@ user2783091 он расширяет JQuery для добавления этой функции. Это не то, что выходит из коробки
JorgeeFG
3

Это глубоко копирует массивы, объекты, нулевые и другие скалярные значения, а также глубоко копирует любые свойства не встроенных функций (что довольно редко, но возможно). (Для эффективности мы не пытаемся копировать нечисловые свойства для массивов.)

function deepClone (item) {
  if (Array.isArray(item)) {
    var newArr = [];
    for (var i = item.length; i-- > 0;) {
      newArr[i] = deepClone(item[i]);
    }
    return newArr;
  }
  if (typeof item === 'function' && !(/\(\) \{ \[native/).test(item.toString())) {
    var obj;
    eval('obj = '+ item.toString());
    for (var k in item) {
      obj[k] = deepClone(item[k]);
    }
    return obj;
  }
  if (item && typeof item === 'object') {
    var obj = {};
    for (var k in item) {
      obj[k] = deepClone(item[k]);
    }
    return obj;
  }
  return item;
}
Бретт Замир
источник
3

Я использую новый метод ECMAScript 6 Object.assign :

let oldObject = [1,3,5,"test"];
let newObject = Object.assign({}, oldObject);

первый аргумент этого метода - массив, который нужно обновить, мы передаем пустой объект, потому что хотим получить новый объект.

мы также можем использовать этот синтаксис, который такой же, но более короткий:

let newObject = [...oldObject];
Читиви Малек
источник
Обратите внимание, что эти подходы будут только копировать ссылки на массивы и объекты в массиве, и не будут делать их новые копии. Ожидайте, что это сломается для многомерных структур.
Бен Уилер
2

Мы можем изобрести простой рекурсивный метод Array для клонирования многомерных массивов. В то время как объекты во вложенных массивах сохраняют свои ссылки на соответствующие объекты в исходном массиве, массивы не будут.

Array.prototype.clone = function(){
  return this.map(e => Array.isArray(e) ? e.clone() : e);
};

var arr = [ 1, 2, 3, 4, [ 1, 2, [ 1, 2, 3 ], 4 , 5], 6 ],
    brr = arr.clone();
brr[4][2][1] = "two";
console.log(JSON.stringify(arr));
console.log(JSON.stringify(brr));

Redu
источник
2

В JavaScript копирование массивов и объектов изменяет исходные значения, поэтому Deep Copy является решением для этого.

Глубокая копия означает на самом деле создание нового массива и копирование значений, поскольку все, что происходит с ним, никогда не повлияет на исходный.

JSON.parseи JSON.stringifyэто лучший и простой способ глубокого копирования. В JSON.stringify()метод преобразует значение JavaScript в JSON string.The JSON.parse()метод анализирует строку JSON, конструируя значение JavaScript или объект , описанный в строке.

// Глубокий клон

let a = [{ x:{z:1} , y: 2}];
let b = JSON.parse(JSON.stringify(a));
b[0].x.z=0

console.log(JSON.stringify(a)); //[{"x":{"z":1},"y":2}]
console.log(JSON.stringify(b)); // [{"x":{"z":0},"y":2}]

Для более подробной информации: читайте здесь

Биджай Рай
источник
1
Это лучшее решение. Спасибо.
Николай
1

с помощью jQuery:

var target= [];
$.each(source, function() {target.push( $.extend({},this));});
lujan99
источник
1

Следующий код выполнит рекурсивно глубокое копирование объектов и массива :

function deepCopy(obj) {
if (Object.prototype.toString.call(obj) === '[object Array]') {
    var out = [], i = 0, len = obj.length;
    for ( ; i < len; i++ ) {
        out[i] = arguments.callee(obj[i]);
    }
    return out;
}
if (typeof obj === 'object') {
    var out = {}, i;
    for ( i in obj ) {
        out[i] = arguments.callee(obj[i]);
    }
    return out;
}
return obj;
}

Источник

Франк Дернонкур
источник
arguments.calleeнедоступен в строгом режиме и имеет проблемы с производительностью в противном случае.
Бретт Замир,
1

Несколько элегантных способов глубокого клонирования в 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 () для клонирования объектов

blazehub
источник
0

Я думаю, что удалось написать общий метод глубокого клонирования любой структуры JavaScript, в основном с использованием, Object.createкоторый поддерживается во всех современных браузерах. Код выглядит так:

function deepClone (item) {
  if (Array.isArray(item)) {
    var newArr = [];

    for (var i = item.length; i-- !== 0;) {
      newArr[i] = deepClone(item[i]);
    }

    return newArr;
  }
  else if (typeof item === 'function') {
    eval('var temp = '+ item.toString());
    return temp;
  }
  else if (typeof item === 'object')
    return Object.create(item);
  else
    return item;
}
ozantunca
источник
Object.createбудет рассматриваться itemкак прототип объекта, но это отличается от клонирования. Если itemэто изменение, изменения будут отражены в его «клоне» и наоборот. Этот подход не работает.
Бретт Замир
0

Также для клонирования объектов я собирался предложить ECMAScript 6 reduce():

const newArray=myArray.reduce((array, element)=>array.push(Object.assign({}, element)), []);

Но, честно говоря, мне больше нравится ответ @dinodsaurus. Я просто выкладываю эту версию здесь как еще один вариант, но лично я буду использовать, map()как предложено @dinodsaurus.

Гаррет Уилсон
источник
0

В зависимости от того, есть ли у вас Underscore или Babel, здесь есть эталон другого способа глубокого клонирования массива.

https://jsperf.com/object-rest-spread-vs-clone/2

Похоже, Babel самый быстрый.

var x = babel({}, obj)
Ромуальд
источник
0
       var game_popularity = [
            { game: "fruit ninja", popularity: 78 },
            { game: "road runner", popularity: 20 },
            { game: "maze runner", popularity: 40 },
            { game: "ludo", popularity: 75 },
            { game: "temple runner", popularity: 86 }
        ];
        console.log("sorted original array before clonning");
        game_popularity.sort((a, b) => a.popularity < b.popularity);
        console.log(game_popularity);


        console.log("clone using object assign");
        const cl2 = game_popularity.map(a => Object.assign({}, a));
        cl2[1].game = "clash of titan";
        cl2.push({ game: "logan", popularity: 57 });
        console.log(cl2);


        //adding new array element doesnt reflect in original array
        console.log("clone using concat");
        var ph = []
        var cl = ph.concat(game_popularity);

        //copied by reference ?
        cl[0].game = "rise of civilization";

        game_popularity[0].game = 'ping me';
        cl.push({ game: "angry bird", popularity: 67 });
        console.log(cl);

        console.log("clone using ellipses");
        var cl3 = [...game_popularity];
        cl3.push({ game: "blue whale", popularity: 67 });
        cl3[2].game = "harry potter";
        console.log(cl3);

        console.log("clone using json.parse");
        var cl4 = JSON.parse(JSON.stringify(game_popularity));
        cl4.push({ game: "home alone", popularity: 87 });
        cl4[3].game ="lockhead martin";
        console.log(cl4);

        console.log("clone using Object.create");
        var cl5 = Array.from(Object.create(game_popularity));
        cl5.push({ game: "fish ville", popularity: 87 });
        cl5[3].game ="veto power";
        console.log(cl5);


        //array function
        console.log("sorted original array after clonning");
        game_popularity.sort((a, b) => a.popularity < b.popularity);
        console.log(game_popularity);


        console.log("Object.assign deep clone object array");
        console.log("json.parse deep clone object array");
        console.log("concat does not deep clone object array");
        console.log("ellipses does not deep clone object array");
        console.log("Object.create does not deep clone object array");


        Output:


        sorted original array before clonning
        [ { game: 'temple runner', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'ludo', popularity: 75 },
        { game: 'maze runner', popularity: 40 },
        { game: 'road runner', popularity: 20 } ]
        clone using object assign
        [ { game: 'temple runner', popularity: 86 },
        { game: 'clash of titan', popularity: 78 },
        { game: 'ludo', popularity: 75 },
        { game: 'maze runner', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'logan', popularity: 57 } ]
        clone using concat
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'ludo', popularity: 75 },
        { game: 'maze runner', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'angry bird', popularity: 67 } ]
        clone using ellipses
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'harry potter', popularity: 75 },
        { game: 'maze runner', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'blue whale', popularity: 67 } ]
        clone using json.parse
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'harry potter', popularity: 75 },
        { game: 'lockhead martin', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'home alone', popularity: 87 } ]
        clone using Object.create
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'harry potter', popularity: 75 },
        { game: 'veto power', popularity: 40 },
        { game: 'road runner', popularity: 20 },
        { game: 'fish ville', popularity: 87 } ]
        sorted original array after clonning
        [ { game: 'ping me', popularity: 86 },
        { game: 'fruit ninja', popularity: 78 },
        { game: 'harry potter', popularity: 75 },
        { game: 'veto power', popularity: 40 },
        { game: 'road runner', popularity: 20 } ]

        Object.assign deep clone object array
        json.parse deep clone object array
        concat does not deep clone object array
        ellipses does not deep clone object array
        Object.create does not deep clone object array
Санграм
источник