JavaScript'te bir nesneyi derinlemesine klonlamanın en etkili yolu nedir?

Bir JavaScript nesnesini klonlamanın en etkili yolu nedir? obj = eval(uneval(o));kullanıldığını gördüm, ancak [bu standart değil ve yalnızca Firefox tarafından destekleniyor][1].<br/><br/>obj = JSON gibi şeyler yaptım.parse(JSON.stringify(o));` gibi şeyler yaptım ancak verimliliği sorguladım.

Ayrıca çeşitli kusurları olan özyinelemeli kopyalama işlevleri de gördüm.
Kanonik bir çözüm bulunmamasına şaşırdım.

Çözüm

Yerli derin klonlama

Buna "structured cloning" deniyor, Node 11 ve sonrasında deneysel olarak çalışıyor ve umarım tarayıcılara da gelir. Daha fazla ayrıntı için bu yanıta bakın.

Veri kaybı ile hızlı klonlama - JSON.parse/stringify

Nesnenizde Date, fonksiyonlar, undefined, Infinity, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, sparse Arrays, Typed Arrays veya diğer karmaşık türleri kullanmıyorsanız, bir nesneyi derinlemesine klonlamak için çok basit bir astar vardır:

JSON.parse(JSON.stringify(object))

const a = {
  string: 'string',
  number: 123,
  bool: false,
  nul: null,
  date: new Date(),  // stringified
  undef: undefined,  // lost
  inf: Infinity,  // forced to 'null'
  re: /.*/,  // lost
}
console.log(a);
console.log(typeof a.date);  // Date object
const clone = JSON.parse(JSON.stringify(a));
console.log(clone);
console.log(typeof clone.date);  // result of .toISOString()

Kıyaslamalar için Corban'ın cevabına bakınız.

Kütüphane kullanarak güvenilir klonlama

Nesneleri klonlamak önemsiz olmadığından (karmaşık tipler, dairesel referanslar, fonksiyon vb.), çoğu büyük kütüphane nesneleri klonlamak için fonksiyon sağlar. Tekerleği yeniden icat etmeyin - zaten bir kütüphane kullanıyorsanız, nesne klonlama işlevine sahip olup olmadığını kontrol edin. Örneğin,

ES6

Bütünlük için, ES6'nın iki sığ kopyalama mekanizması sunduğunu unutmayın: Object.assign() ve spread operator.

Yorumlar (24)

Eğer yerleşik bir tane yoksa, deneyebilirsiniz:

function clone(obj) {
    if (obj === null || typeof (obj) !== 'object' || 'isActiveClone' in obj)
        return obj;

    if (obj instanceof Date)
        var temp = new obj.constructor(); //or new Date(obj);
    else
        var temp = obj.constructor();

    for (var key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            obj['isActiveClone'] = null;
            temp[key] = clone(obj[key]);
            delete obj['isActiveClone'];
        }
    }
    return temp;
}
Yorumlar (11)
function clone(obj)
 { var clone = {};
   clone.prototype = obj.prototype;
   for (property in obj) clone[property] = obj[property];
   return clone;
 }
Yorumlar (5)