Koks veiksmingiausias būdas klonuoti "JavaScript" objektą? Esu matęs, kad naudojamas obj = eval(uneval(o));
, bet tai nestandartinis variantas, kurį palaiko tik "Firefox".
Esu daręs tokius dalykus kaip obj = JSON.parse(JSON.stringify(o));
, bet abejoju dėl efektyvumo.
Taip pat esu matęs rekursinio kopijavimo funkcijų su įvairiais trūkumais.
Aš'stebiuosi, kad nėra kanoninio sprendimo.
Tai vadinama "struktūrizuotu klonavimu", eksperimentiniu būdu veikia "Node 11" ir vėlesnėse versijose ir, tikiuosi, bus įdiegta naršyklėse. Daugiau informacijos žr. šis atsakymas.
Jei objekte nenaudojate Date
, funkcijų, undefined
, Infinity
, RegExps, Maps, Sets, Blobs, FileLists, ImageData, retų masyvų, tipinių masyvų ar kitų sudėtingų tipų, labai paprasta viena eilutė giliam objekto klonavimui yra:
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()
Žr. Corban's answer, kur pateikiami lyginamieji pavyzdžiai.
Kadangi objektų klonavimas nėra trivialus (sudėtingi tipai, žiedinės nuorodos, funkcijos ir t. t.), dauguma pagrindinių bibliotekų pateikia objektų klonavimo funkciją. Neišradinėkite dviračio - jei jau naudojate biblioteką, patikrinkite, ar ji turi objektų klonavimo funkciją. Pvz,
cloneDeep
; galima importuoti atskirai per modulį lodash.clonedeep ir tai tikriausiai geriausias pasirinkimas, jei dar nenaudojate bibliotekos, kuri turi gilaus klonavimo funkcijąangular.copy
jQuery.extend(true, { }, oldObject)
; .clone()
klonuoja tik DOM elementusIšsamumo dėlei atkreipkite dėmesį, kad ES6 siūlo du negilaus kopijavimo mechanizmus: Object.assign()
ir spread operator.
Jei nėra jokio integruoto, galite pabandyti:
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;
}