Javascript bir dizi nesneleri nasıl klonlamak?


421

... her nesnenin aynı dizideki diğer nesnelere de referansları var mı?

Bu soruna ilk geldiğimde,

var clonedNodesArray = nodesArray.clone()

var ve javascript nesnelerin klonlanması hakkında bilgi aradı. (Aynı @JohnResig tarafından cevaplandı) StackOverflow hakkında bir soru buldum ve o jQuery ile yapabileceğini belirtti

var clonedNodesArray = jQuery.extend({}, nodesArray);

bir nesneyi klonlamak. Bu olsa denedim, bu sadece dizideki nesnelerin referanslarını kopyalar. Yani ben

nodesArray[0].value = "red"
clonedNodesArray[0].value = "green"

her iki nodesArray [0] ve clonedNodesArray [0] 'ın değeri "yeşil" olur. Sonra denedim

var clonedNodesArray = jQuery.extend(true, {}, nodesArray);

Bu, bir Nesneyi derin kopyalar, ancak sırasıyla Firebug ve Opera Dragonfly'den " çok fazla özyineleme " ve " kontrol yığını taşması " iletileri aldım.

Nasıl yapardın? Bu yapılmaması gereken bir şey mi? Javascript bunu yapmanın yeniden kullanılabilir bir yolu var mı?

Yanıtlar:


106

Sığ kopyanızla ilgili sorun, tüm nesnelerin klonlanmamasıdır. Her bir nesneye yapılan referanslar her dizide benzersiz olsa da, sonuçta üzerine geldiğinizde, daha önce olduğu gibi aynı nesneyle uğraşıyorsunuz demektir. Klonlama şeklinizde yanlış bir şey yok ... Array.slice () kullanılarak aynı sonuç ortaya çıkar.

Derin kopyanızın sorunlara neden olmasının nedeni, dairesel nesne referanslarına son vermenizdir. Derin gidebildiği kadar derine iner ve bir çemberiniz varsa, tarayıcı sönene kadar sonsuz devam eder.

Veri yapısı yönlendirilmiş bir asiklik grafik olarak gösterilemiyorsa, derin klonlama için çok amaçlı bir yöntem bulabileceğinizden emin değilim. Döngüsel grafikler birçok zor köşe durumu sağlar ve bu yaygın bir işlem olmadığından, herkesin tam bir çözüm yazdığından şüphe duyuyorum (eğer mümkünse - olmayabilir! Ama şimdi titiz bir kanıt yazmaya çalışacak zamanım yok.). Bu sayfada bu konuda bazı iyi yorumlar buldum .

Dairesel referanslı bir Nesne Dizisinin derin bir kopyasına ihtiyacınız varsa, özel veri yapınızı işlemek için kendi yönteminizi kodlamanız gerekeceğine inanıyorum, böylece çok geçişli bir klon olacak:

  1. Birinci turda, dizideki diğer nesnelere başvurmayan tüm nesnelerin bir klonunu yapın. Her nesnenin kökenini takip edin.
  2. İkinci turda, nesneleri birbirine bağlayın.

1
@PatrickdeKleijn cevabı için sabit bağlantı: web.archive.org/web/20140222022056/http://my.opera.com/…
Mike Szyndel

531

Nesneleriniz JSON serileştirilebilir içerik içerdiği sürece (işlev yok Number.POSITIVE_INFINITY, hayır , vb.) Dizileri veya nesneleri klonlamak için herhangi bir döngüye gerek yoktur. İşte saf vanilya tek satırlık bir çözüm.

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

Aşağıdaki yorumları özetlemek gerekirse, bu yaklaşımın birincil avantajı, sadece dizinin kendisini değil, dizinin içeriğini de klonlamasıdır. Birincil dezavantajlar sadece JSON serileştirilebilir içerik üzerinde çalışma sınırıdır ve performansı ( slicetemel bir yaklaşımdan çok daha kötüdür ).


118
Bu JSON verileri için işe yarayabilir, ancak diziniz herhangi bir işlev veya yöntem içeren nesnelerin örneklerini içeriyorsa, onlara veda edin.
sp0rkyd0rky

12
Infinity değerini içeren bir diziniz varsa dikkatli olun. Bu değer kaybolur (daha sonra null olur). ( jsfiddle.net/klickagent/ehm4bd3s )
klickagent.ch

13
Diziniz (hatta sadece temel öğeler içerir ve / veya kendilerini yalnız dize / numarayı / boole ilkeller ihtiva nesneler sürece bu sadece genel bir kötü yaklaşımdır nullve undefinedJSON bunları desteklemediği, sorunlar olacaktır). Ayrıca, old_array.slice(0);hem daha iyi hem de daha hızlı çalışacak olandan çok daha az verimli bir işlemdir .
XML

2
dizinin nesnesinde DateTime varsa, DateTime yerine dize döndürülür! yeni Tarih! == JSON.parse (JSON.stringify (yeni Tarih))
MarkosyanArtur

2
OP'nin yukarıdaki bu cevabın tamamen görmezden geldiği anahtar satırı: ... her bir nesnenin aynı dizideki diğer nesnelere de referansları var mı?
XML

288

Object.assign ile bir dizi nesnenin klonlanmasını çözdüm

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

hatta yayılmış sözdizimi ile daha da kısa

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

15
Ancak myArray bir grup Dinozor içeriyorsa, newArray bir grup Nesne içerir. Bu topal, kabul etmiyor musun?
Matthew James Davis

3
En iyi yaklaşım, bu JSON.parse (JSON.stringify (nodesArray)) onları kaybetme sonra hayatta, Rathen nesneler işlevlerini tutar olarak
scipper

14
@MatthewJamesDavis {}ile değiştirerek bunu çözebilirsiniz new Dinosaur().
Agargara

5
sığ kopya değil derin kopya
sultan aslam

1
Böylece, söz konusu nesnelerin sadece ilkel özellikler ... içeriyorsa hangi i sayesinde, gereken budur, nesneler dizisi için çok çalışır
Mojave

154

İhtiyacınız olan tek şey sığ bir kopyaysa, gerçekten kolay bir yol:

new_array = old_array.slice(0);

6
Geçmek zorunda olduğunuzu sanmıyorum 0, .slice()en azından
kromda

112
Bu aslında işe yaramıyor, değil mi? Yani, bir dizi nesneyi nasıl kopyalayacağımız sorusuna bir cevap değil. Bu basit bir diziyi klonlamak için bir çözümdür.
bozdoz

35
Aslında bu bir nesne dizisi için işe yaramaz. Döndürülen dizi sliceyeni bir dizi olacak, ancak orijinal dizi nesnelerine başvuruları içerecektir.
Sergio

4
Bu yalnızca "generics" int, string vb. İçin çalışır, ancak bir dizi nesne için çalışmaz.
Stefan Michev

5
aslında klonlamayan nesne dizisi için, new_array'a güncelleme old_array öğesini de güncelleyecektir.
Anas

44

Bu klonu yapmanın en iyi ve en güncel yolu aşağıdaki gibidir:

...ES6 forma operatörünü kullanma .

İşte en basit örnek:

var clonedObjArray = [...oldObjArray];

Bu şekilde diziyi tek tek değerlere yayarız ve [] operatörü ile yeni bir diziye koyarız.

Aşağıda, farklı çalışma yöntemlerini gösteren daha uzun bir örnek verilmiştir:

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} ]


2
Eski tarayıcılarla işe yaramayacak iyi bir modern yanıt (IE 11 gibi)
Jealie

1
@Jealie Sanırım KingpinEX, es6'yı Babel ile evrensel olarak daha kullanışlı bir şeye aktaran ya da neye sahip olanlara bu cevabı hedefliyor.
ruffin

61
Bu sadece diziyi kopyalar, dizideki her nesneyi değil.
Toivo Säwén

31
@ ToivoSäwén'in söylediklerini takip etmek için, bu dizideki nesneleri derin kopyalamayacaktır. Orijinal nesnelere hala başvuruda bulunacaktır, bu yüzden onları değiştirirseniz orijinal diziyi de etkileyecektir.
Joel Kinzel

3
Sadece ilkel için çalışır. Şunu deneyin: objArray [0] .a = 3; clonedArray öğesinde nesnenin başvurusunun aynı kaldığını göreceksiniz.
Sergio Correa

25

Bu benim için çalışıyor:

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

Ve dizideki nesnelerin derin kopyasına ihtiyacınız varsa:

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

1
Bu işe yarayacak gibi görünüyor. Ben kapsamlı jQuery kullanımı önlemek için çalışıyorum, bu yüzden benim durumumda kullanmayacağım, ama bir for döngüsü ve ... için işe yarayacak.
bozdoz

19
$.evalJSON($.toJSON(origArray));

2
Sen kullanarak gerekecektir jquery json Eklentinin bu kullanmak code.google.com/p/jquery-json
wmitchell

32
JQ (modern tarayıcılarda ince) olmadan:JSON.parse(JSON.stringify(origArray));
forresto

Bu yorumu faydalı buldum. Uygulamamda KnockoutJS gözlemlenebilir özellikleri uygulanmış bir dizi nesnenin bir kopyasını yapmam gerekiyordu. Kopyada sadece değerlere ihtiyaç vardı, gözlemlenebilirliğe değil. SADECE değerlerinin bir kopyasını oluşturmak için JSON.parse (ko.toJSON (origArray)) VEYA ko.utils.parseJson (ko.toJSON (origArray)) kullandım. Sadece 2 sentim ve çözümüme ulaşmama yardım ettiğiniz için teşekkür ederim.
wavedrop

6
JSON.parse(JSON.stringify(origArray)); kesinlikle en basit çözümdür.
yorkw

jQuery genellikle gereksizdir. youmightnotneedjquery.com
ADJenks

9

Harita eskisinden yeni bir dizi oluşturur (eskisine başvurmadan) ve haritanın içinde yeni nesne oluşturursunuz ve özellikler (anahtarlar) üzerinde yinelenir ve eski Array nesnesinden yeni nesneye karşılık gelen özelliklere değerler atarsınız.

Bu, tam olarak aynı nesne dizisini yaratacaktır.

let newArray = oldArray.map(a => {
               let newObject = {};
               Object.keys(a).forEach(propertyKey => {
                    newObject[propertyKey] = a[propertyKey];
               });
               return newObject ;
});

8

Ağrılı özyineleme yapmadan ve söz konusu nesnenin tüm ince ayrıntılarını bilmeden bunu yapmanın basit bir yolu olabilir. JQuery kullanarak, jQuery kullanarak nesnenizi JSON'a dönüştürmeniz $.toJSON(myObjectArray), ardından JSON dizenizi alıp bir nesneye geri değerlendirmeniz yeterlidir . BAM! Bitti ve bitti! Sorun çözüldü. :)

var oldObjArray = [{ Something: 'blah', Cool: true }];
var newObjArray = eval($.toJSON(oldObjArray));

21
Bazı modern tarayıcılarda yerleşik JSON yöntemi vardır, böylece bunu yapabilirsiniz: daha hızlı olması gereken JSON.parse (JSON.stringify (MY_ARRAY)). İyi öneri.
Nicolas R

1
Ve onlar kullanmıyorsanız json2 değil eval.
kamranicus

Bu korkunç bir performansa sahip, ama ne yazık ki gördüğüm en iyi cevap: /
Dvid Silva

Kullanıcı verileriyle hiçbir şey değerlendirmeyin. Tercihen asla kullanmayın eval(). Bu bir güvenlik riski.
ADJenks

8

"Javascript'te bir nesne dizisi klonlama" sorununa basit ve açık bir çözüm gibi görünmüyor çünkü bu soruyu cevaplıyorum:

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

Bu çözüm dizi değerlerini yineler, sonra nesne anahtarlarını yineler, ikincisini yeni bir nesneye kaydeder ve sonra bu yeni nesneyi yeni bir diziye iter.

Bkz. Jsfiddle . Not: Basit .slice()veya [].concat()nesneler için yeterli değildir dahilinde diziden.


Cevabınız için teşekkürler, ama cevabın eksikliklerini vurgulamalısınız. Nesnelerin içinde nesneler olduğunda işe yaramaz .. değil mi?
Sert

sığ kopya oluşturur. derin değil
sultan aslam

bir yere özyineleme eklemeniz gerekir
DGoiko

6

JQuery expand iyi çalışıyor, sadece bir nesne yerine bir dizi klonladığınızı belirtmeniz gerekir ( expand yönteminin parametresi olarak {} yerine [] öğesini not edin ):

var clonedNodesArray = jQuery.extend([], nodesArray);

2
Hmm, bunu küçümserseniz, lütfen bunu neden yaptığınız hakkında bir yorum ekleyebilir misiniz? Veya önce kodu deneyebilir ve çalışıp çalışmadığını görebilir misiniz? Teşekkürler;)
Stef

1
İlk dizideki bir nesneyi değiştirdikten sonra, ikinci dizideki nesne değiştirilir, bu yüzden sorun olmaz.
Spikolynn

6

Bu yöntem çok basittir ve orijinal diziyi değiştirmeden klonunuzu değiştirebilirsiniz.

// 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
Bu, derin iki seviyeleri var oysa basit bir kopyasını yapar [...oldArray]ve oldArray.slice(0)bir sığ yapmak bir seviye derine kopyalayın. Yani bu süper kullanışlı, ama gerçek bir tam derin klon değil.
Ben Wheeler

gerçek derin klon lodash.clonedeepnpm kullanılarak yapılabilir
revelt

5

Daniel Lew'in belirttiği gibi, döngüsel grafiklerin bazı sorunları var. Bu problemim olsaydı ya özelclone() karşılaşırsam, sorunlu nesnelere yöntemler zaten kopyaladığım nesneleri hatırlarım.

Bunu bir değişkenle yapardım copyCount her kopyaladığınızda 1 artan . copyCountGeçerli kopyalama işleminden daha düşük olan bir nesne kopyalanır. Değilse, zaten var olan kopyaya başvurulmalıdır. Bu, orijinalden kopyasına bağlanmayı gerekli kılar.

Hala bir sorun var: Bellek. Bir nesneden diğerine bu referansa sahipseniz, tarayıcının bu nesneleri her zaman bir yerden başvurduğu için serbest bırakamayacağı muhtemeldir. Tüm kopya referanslarını Null olarak ayarladığınız ikinci bir geçiş yapmanız gerekir. (Bunu yaparsanız , ikinci geçişte değeri sıfırlayabileceğiniz için copyCountbir boolean isCopiedyeterli olacaktır.)


4

Array.slice, bir diziyi veya dizinin bir bölümünü kopyalamak için kullanılabilir .. http://www.devguru.com/Technologies/Ecmascript/Quickref/Slice.html Bu, dizeler ve sayılarla çalışır .. - bir dizi diğerini etkilemez - ancak nesneler hala referans olarak kopyalanır, bu nedenle bir dizideki başvurulan nesnelerde yapılan değişiklikler diğer dizide bir etkiye sahip olur.

Bunun için yararlı olabilecek bir JavaScript geri alma yöneticisi örneği: http://www.ridgway.co.za/archive/2007/11/07/simple-javascript-undo-manager-for-dtos.aspx


Biliyorum. Bunu uygulamak istediğim nedeni, geri izleme ile bir CSP sorununu çözmeye çalışıyorum çünkü. Geri izlemenin uygulanmasının yollarından birinin, bu tür anlık görüntüleri bir yığına klonlayarak değişkenlerin atama durumunu "anlık görüntü almak" gibi olabileceğini düşündüm.
wallyqs

... ve aslında, çok kötü bir fikir olabilir.
wallyqs

Bu yaklaşım diğer senkronizasyon komplikasyonları olabilir :) .. Eğer dizi değiştiriliyor değil nasıl anlarım ederken bir anlık götürüyorsun?
markt

Yazarın javascript kullanarak basit bir geri alma yöneticisi uyguladığı bir makaleye bağlantı eklendi ..
markt

4

Benim yaklaşımım:

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

bana orijinal dizinin güzel, temiz, derin bir klonunu verir - nesnelerin hiçbiri orijinaline geri gönderilmez :-)


Bu jquery kullanarak en iyi çözümdür. kısa ve güzel.
John Henckel

1
Bir performans testi yaptım ve bu çözüm JSON.stringify çözümünden yaklaşık 2 kat daha hızlı görünüyor.
meehocz

4

lodash'ın cloneDeepbu amaçlar için işlevi vardır :

var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);

4

Derin klon uygulamak istiyorsanız JSON.parse (JSON.stringify ({} veya [])) kullanın

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

forget eval () (JS'nin en yanlış kullanılmış özelliğidir ve kodu yavaşlatır) ve dilim (0)

Bu benim için en iyi çözüm:

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;
};

3

Bu sorun beni oldukça hayal kırıklığına uğrattı. Görünüşe göre, $ .extend yöntemine genel bir Array içinde gönderdiğinizde sorun ortaya çıkıyor. Yani, düzeltmek için biraz kontrol ekledim ve genel diziler, jQuery dizileri ve herhangi bir nesneyle mükemmel çalışıyor.

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);
    },
});

Şunu kullanarak çağır:

var arrNewArrayClone = jQuery.deepclone(arrOriginalArray);
// Or more simply/commonly
var arrNewArrayClone = $.deepclone(arrOriginalArray);

deepclone? Jquery-1.9.1 kullanıyorum ve bu yöntemi desteklemiyor. Daha modern bir versiyonun yöntemi midir?
user5260143

@ user2783091 o işlevi eklemek için JQuery genişletiyor. Kutusundan çıkan bir şey değil
JorgeeFG

3

Bu, dizileri, nesneleri, null ve diğer skaler değerleri derinden kopyalar ve ayrıca yerel olmayan işlevlerdeki (oldukça nadir ancak mümkün olan) herhangi bir özelliği derinden kopyalar. (Verimlilik için, dizilere sayısal olmayan özellikler kopyalamaya çalışmaz.)

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

Yeni ECMAScript 6 Object.assign yöntemini kullanıyorum:

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

Bu yöntemin ilk argümanı güncellenecek dizidir, boş bir nesne geçiririz çünkü yeni bir nesneye sahip olmak isteriz.

aynı ama daha kısa olan bu sözdizimini de kullanabiliriz:

let newObject = [...oldObject];

Bu yaklaşımların yalnızca dizideki diziler ve nesneler için referansları kopyalayacağını ve bunların yeni kopyalarını oluşturmayacağını unutmayın. Bunun çok boyutlu yapılar için kırılmasını bekleyin.
Ben Wheeler

2

Çok boyutlu dizileri klonlamak için basit bir özyinelemeli Array yöntemi icat edebiliriz. Yuvalanmış dizilerdeki nesneler kaynak dizideki karşılık gelen nesnelere referanslarını korurken, diziler olmaz.

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));


2

JavaScript'te, dizi ve nesne kopyası başlangıç ​​değerlerini değiştirir, bu nedenle bunun için Derin kopya çözümdür.

Derin bir kopya, aslında yeni bir dizi oluşturmak ve değerlerin üzerine kopyalamak anlamına gelir, çünkü ona ne olursa olsun, orijinali asla etkilemez.

JSON.parseve JSON.stringifyDerin kopyalamanın en iyi ve basit yoludur. JSON.stringify()Yöntem, bir JavaScript değerini bir JSON dizesine dönüştürür . Yöntem, bir JSON.parse()JSON dizesini ayrıştırır ve dize tarafından açıklanan JavaScript değerini veya nesnesini oluşturur.

// Derin Klon

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}]

Daha fazla bilgi için: Buraya Okuyun


1
Bu en iyi çözüm. Teşekkür ederim.
Nikolay

1

jQuery ile:

var target= [];
$.each(source, function() {target.push( $.extend({},this));});

1

Aşağıdaki kod , nesnelerin ve dizinin özyinelemeli olarak derinlemesine kopyalanmasını sağlar :

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;
}

Kaynak


arguments.calleekatı modda mevcut değildir ve aksi takdirde performans sorunları vardır.
Brett Zamir


0

Genel Object.createolarak tüm modern tarayıcılarda desteklenen herhangi bir JavaScript yapısını derin klonlama için genel bir yöntem yazmayı başardım . Kod şöyle:

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;
}

Object.createitemnesnenin prototipi gibi davranacaktır , ancak bu klonlamadan farklıdır. Eğer itemmodifiye edilmiş, değişiklikler onun "klon" ve tersi de yansıyacaktır. Bu yaklaşım işe yaramıyor.
Brett Zamir

0

Nesneleri de klonlamak için ECMAScript 6'yı önerecektim reduce():

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

Ama açıkçası @dinodsaurus'un cevabını daha iyi seviyorum. Bu sürümü başka bir seçenek olarak buraya koyuyorum, ancak şahsen map()@dinodsaurus tarafından önerildiği gibi kullanacağım.



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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.