Kāds ir visefektīvākais veids, kā dziļi klonēt objektu JavaScript programmā?

Kāds ir efektīvākais veids, kā klonēt JavaScript objektu? Esmu redzējis, ka tiek izmantots obj = eval(uneval(o));, bet tas ir nestandarta un to atbalsta tikai Firefox.


Es'esmu darījis tādas lietas kā obj = JSON.parse(JSON.stringify(o));, bet šaubos par efektivitāti.

Es'esmu redzējis arī rekursīvas kopēšanas funkcijas ar dažādiem trūkumiem.
Es'esmu pārsteigts, ka nav kanoniska risinājuma.

Risinājums

Native deep cloning

To sauc par "strukturētu klonēšanu", eksperimentāli tas darbojas Node 11 un jaunākajās versijās un, cerams, tiks ieviests pārlūkprogrammās. Sīkāku informāciju sk. šajā atbildē.

Ātra klonēšana ar datu zudumu - JSON.parse/stringify

Ja objektā neizmantojat Date, funkcijas, undefined, Infinity, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, retākus masīvus, tipveida masīvus vai citus sarežģītus tipus, ļoti vienkārša viena līnija, lai dziļi klonētu objektu, ir:

Klonēšana: 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()

Sk. Corban's atbildi, lai uzzinātu etalonus.

Uzticama klonēšana, izmantojot bibliotēku

Tā kā objektu klonēšana nav triviāla (sarežģīti tipi, apļveida atsauces, funkcijas utt.), lielākā daļa lielāko bibliotēku piedāvā funkciju objektu klonēšanai. Neizgudrojiet velosipēdu no jauna - ja jau izmantojat kādu bibliotēku, pārbaudiet, vai tajā ir objektu klonēšanas funkcija. Piemēram,

ES6

Pilnīguma labad jāatzīmē, ka ES6 piedāvā divus seklās kopēšanas mehānismus: Object.assign() un spread operators.

Komentāri (24)

Ja nav iebūvēta neviena, varat izmēģināt:

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;
}
Komentāri (11)
function clone(obj)
 { var clone = {};
   clone.prototype = obj.prototype;
   for (property in obj) clone[property] = obj[property];
   return clone;
 }
Komentāri (5)