Wat is de meest efficiënte manier om een JavaScript-object te klonen? Ik'heb gezien dat obj = eval(uneval(o));
wordt gebruikt, maar dat'is niet-standaard en alleen ondersteund door Firefox.
Ik'heb dingen gedaan als obj = JSON.parse(JSON.stringify(o));
maar zet vraagtekens bij de efficiëntie.
Ik'heb ook recursieve kopieerfuncties gezien met verschillende gebreken.
Ik'ben verbaasd dat er geen canonieke oplossing bestaat.
Het's genoemd "structured cloning", werkt experimenteel in Node 11 en later, en hopelijk zal het landen in browsers. Zie dit antwoord voor meer details.
Als je geen Date
s, functies, undefined
, Infinity
, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, sparse Arrays, Typed Arrays of andere complexe types binnen je object gebruikt, is een zeer eenvoudige one liner om een object diep te klonen:
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()
Zie Corban's antwoord voor benchmarks.
Omdat het klonen van objecten niet triviaal is (complexe types, circulaire verwijzingen, functie enz.), bieden de meeste grote bibliotheken functie om objecten te klonen. Don't reinvent the wheel - als je'al een bibliotheek gebruikt, controleer dan of deze een functie voor het klonen van objecten heeft. Bijvoorbeeld,
cloneDeep
; kan afzonderlijk worden geïmporteerd via de lodash.clonedeep module en is waarschijnlijk uw beste keuze als u're niet al een bibliotheek gebruikt die een diepe kloonfunctie biedtangular.copy
jQuery.extend(true, { }, oldObject)
; .clone()
kloont alleen DOM-elementenVoor de volledigheid, merk op dat ES6 twee ondiepe kopieermechanismen biedt: Object.assign()
en de spread operator.
Als er geen ingebouwde was, zou je het kunnen proberen:
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;
}