Was ist der effizienteste Weg, um ein Objekt in Javascript tief zu klonen?

Was ist der effizienteste Weg, um ein JavaScript-Objekt zu klonen? Ich habe gesehen obj = eval(uneval(o)); was aber kein Standard ist und nur von Firefox unterstützt wird .

Ich habe Dinge wie obj = JSON.parse(JSON.stringify(o)); aber bezweifle die Wirksamkeit.

Ich habe auch die rekursiven Kopierfunktionen mit verschiedenen Fehlern gesehen.

Ich bin überrascht, dass es keine kanonische Lösung gibt.

4845
23 сент. von jschrab am 23 sep . 2008-09-23 19:26 2008 um 19:26 Uhr 2008-09-23 19:26
@ 69 Antworten
  • 1
  • 2
  • 3

Hinweis: Dies ist die Antwort auf eine andere Antwort, nicht die richtige Antwort auf diese Frage. Wenn Sie Objekte schnell klonen möchten, folgen Sie bitte den Anweisungen von Corban in Ihrer Antwort auf diese Frage.


Ich möchte beachten, dass die .clone() -Methode in jQuery nur DOM-Elemente .clone() . Um JavaScript-Objekte zu klonen, müssen Sie:

 // Shallow copy var newObject = jQuery.extend({}, oldObject); // Deep copy var newObject = jQuery.extend(true, {}, oldObject); 

Weitere Informationen finden Sie in der jQuery-Dokumentation .

Ich möchte auch darauf hinweisen, dass eine tiefe Kopie tatsächlich viel intelligenter ist als oben gezeigt - dadurch können viele Fallen vermieden werden (z. B. um das DOM-Element tief zu erweitern). Es wird oft im jQuery-Kern und in Plugins mit großer Wirkung verwendet.

4203
23 сент. Antwort von John Resig 23. September 2008-09-23 21:09 08 um 21:09 Uhr 2008-09-23 21:09

Schauen Sie sich diesen Benchmark an: http://jsben.ch/#/bWfk9

In meinen vorherigen Tests, bei denen Geschwindigkeit das Hauptproblem war, stellte ich fest

<Prev> <code> JSON.parse (JSON.stringify (OBJ)) Code>

Der schnellste Weg, um ein Objekt tief zu klonen ( jQuery.extend wird dabei mit dem Deep-Flag um 10-20% überschritten).

jQuery.extend ist ziemlich schnell, wenn das tiefe Werteflag auf false (shallow clone) gesetzt ist. Dies ist eine gute Option, da sie eine zusätzliche Logik für die Typüberprüfung enthält und die Eigenschaften von undefined usw. nicht kopiert. Sie wird jedoch auch etwas >

Wenn Sie die Struktur der Objekte kennen, die Sie zu klonen versuchen, oder wenn Sie tief verschachtelte Arrays vermeiden for (var я in obj) , können Sie eine einfache for (var я in obj) Schleife for (var я in obj) , um Ihr Objekt zu klonen. Dabei wird hasOwnProperty überprüft, und es ist viel schneller als jQuery.

border=0

Wenn Sie versuchen, eine bekannte Objektstruktur in einer Hot-Schleife zu klonen, können Sie VIEL MEHR LEISTUNG erhalten, indem Sie einfach die Klonprozedur einfügen und das Objekt manuell erstellen.

JavaScript-Tracking-Mechanismen for..in Optimierung von for..in Schleifen und das Überprüfen von hasOwnProperty wird Sie ebenfalls ver>

  var clonedObject = { knownProp: obj.knownProp,.. } Код> 

Verwenden Sie die JSON.parse(JSON.stringify(obj)) Methode JSON.parse(JSON.stringify(obj)) für Date Objekte nicht - JSON.stringify(новая дата()) gibt eine Zeichenfolgendarstellung des Datums im ISO-Format zurück, in der JSON.parse() nicht zum Date Objekt zurückkehrt. Weitere Informationen finden Sie in dieser Antwort .

Beachten Sie außerdem, dass in Chrome 65 zumindest das native Klonen nicht geeignet ist. Laut dieser JSPerf ist das eigene Klonen mit dem Erstellen einer neuen Funktion fast 800x >

2046
17 марта '11 в 22:19 2011-03-17 22:19 Die Antwort wird von Corban Brook am 17. März um 22:19 Uhr 2011-03-17 22:19 gegeben

Vorausgesetzt, Sie haben nur Variablen und keine Funktionen in Ihrem Objekt, können Sie einfach Folgendes verwenden:

 var newObject = JSON.parse(JSON.stringify(oldObject)); 
431
04 янв. Die Antwort wird von Sultan Shakir Jan 04 gegeben 2011-01-04 11:05 11 um 11:05 2011-01-04 11:05

Strukturiertes Klonen

Der HTML-Standard enthält einen internen strukturierten Klonierungs- / Serialisierungsalgorithmus , der tiefe Klone von Objekten erstellen kann. Es ist immer noch auf bestimmte integrierte Typen beschränkt, aber zusätzlich zu einigen von JSON unterstützten Typen unterstützt es auch Datumsangaben, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, spärliche Arrays, typisierte Arrays und möglicherweise mehr. ., Es speichert auch Referenzen in den geklonten Daten, wodurch Sie zyklische und rekursive Strukturen verwalten können, die zu Fehlern bei JSON führen können.

Unterstützung in Node.js: experimentell 🙂

Das v8 Modul in Node.js bietet derzeit (ab Node 11) direkt eine strukturierte Serialisierungs-API . Diese Funktionalität wird jedoch als „experimentell“ gekennzeichnet und kann in zukünftigen Versionen geändert oder entfernt werden. Wenn Sie eine kompatible Version verwenden, ist das Klonen eines Objekts so einfach wie folgt:

structdClone structClone structuredClone() in whatwg / html # 793 auf GitHub beschrieben .  Derzeit wird vorgeschlagen, es für die meisten Zwecke so einfach zu verwenden wie: 

MessageChannels- Port zu veröffentlichen.  Der andere Port sendet ein message mit einem strukturierten Klon angehängter Daten .data .  Leider ist das Abhören dieser Ereignisse notwendigerweise asynchron und synchrone Alternativen sind weniger praktisch. 

 const main = async () => { const original = { date: new Date(), number: Math.random() }; original.self = original; const clone = await structuredCloneAsync(original); // They're different objects: console.assert(original !== clone); console.assert(original.date !== clone.date); // They're cyclical: console.assert(original.self === original); console.assert(clone.self === clone); // They contain equivalent values: console.assert(original.number === clone.number); console.assert(Number(original.date) === Number(clone.date)); console.log("Assertions complete."); }; main(); 

Synchroner Workarounds: Schrecklich! 🤢

Es gibt keine guten Optionen für die synchrone Erstellung von strukturierten Klonen. Hier sind ein paar unpraktische Hacks.

history.pushState() und history.replaceState() erstellen einen strukturierten Klon ihres ersten Arguments und weisen diesen Wert history.state . Sie können dies verwenden, um einen strukturierten Klon eines beliebigen Objekts wie folgt zu erstellen:

Notification erstellt einen strukturierten Klon der zugehörigen Daten.  Es wird auch versucht, eine Benachrichtigung für den Benutzer im Browser anzuzeigen. Dies endet jedoch unbeaufsichtigt mit einem Fehler, wenn Sie nicht die Berechtigung zur Benachrichtigung angefordert haben.  Wenn Sie die Erlaubnis für andere Zwecke haben, werden wir die von uns erstellte Mitteilung unverzüglich schließen. 

306
06 июня '12 в 17:59 2012-06-06 17:59 Die Antwort wird Jeremy Banks am 6. Juni 12 um 17:59 2012-06-06 17:59 gegeben

Wenn es nicht eingebaut ist, können Sie Folgendes versuchen:

 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; } 
294
23 сент. Antwort von ConroyP 23. September 2008-09-23 19:38 2008 um 19:38 Uhr 23.09.2008 19:38 Uhr

Effektive Methode zum Klonen (nicht tiefes Klonen) eines Objekts in einer Codezeile

Die Object.assign Methode ist Teil des Standards ECMAScript 2015 (ES6) und erfüllt genau das, was Sie benötigen.

 var clone = Object.assign({}, obj); 

Die Object.assign () -Methode wird verwendet, um die Werte aller aufgezählten Eigenschaften von einem oder mehreren Quellobjekten in das Zielobjekt zu kopieren.

Lesen Sie mehr ...

Polyfill zur Unterstützung älterer Browser:

 if (!Object.assign) { Object.defineProperty(Object, 'assign', { enumerable: false, configurable: true, writable: true, value: function(target) { 'use strict'; if (target === undefined || target === null) { throw new TypeError('Cannot convert first argument to object'); } var to = Object(target); for (var i = 1; i < arguments.length; i++) { var nextSource = arguments[i]; if (nextSource === undefined || nextSource === null) { continue; } nextSource = Object(nextSource); var keysArray = Object.keys(nextSource); for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { var nextKey = keysArray[nextIndex]; var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined  desc.enumerable) { to[nextKey] = nextSource[nextKey]; } } } return to; } }); } 
148
15 дек. Die Antwort wird von Eugene Tiurin am 15. Dezember gegeben. 2015-12-15 10:26 '15 um 10:26 Uhr 2015-12-15 10:26

Code:

 // extends 'from' object with members from 'to'. If 'to' is null, a deep clone of 'from' is returned function extend(from, to) { if (from == null || typeof from != "object") return from; if (from.constructor != Object  from.constructor != Array) return from; if (from.constructor == Date || from.constructor == RegExp || from.constructor == Function || from.constructor == String || from.constructor == Number || from.constructor == Boolean) return new from.constructor(from); to = to || new from.constructor(); for (var name in from) { to[name] = typeof to[name] == "undefined" ? extend(from[name], null) : to[name]; } return to; } 

Test:

 var obj = { date: new Date(), func: function(q) { return 1 + q; }, num: 123, text: "asdasd", array: [1, "asd"], regex: new RegExp(/aaa/i), subobj: { num: 234, text: "asdsaD" } } var clone = extend(obj); 
94
25 июня '09 в 10:53 2009-06-25 10:53 Die Antwort wird von Kamarey am 25. Juni 09 um 10:53 2009-06-25 10:53 gegeben

Das ist was ich benutze:

 function cloneObject(obj) { var clone = {}; for(var i in obj) { if(typeof(obj[i])=="object"  obj[i] != null) clone[i] = cloneObject(obj[i]); else clone[i] = obj[i]; } return clone; } 
86
12 дек. Die Antwort wird von Alan am 12. Dezember gegeben. 2009-12-12 01:47 09 um 1:47 2009-12-12 01:47

Deep Copy-Leistung: vom besten bis zum schlechtesten

  • Neuzuordnung "=" (nur String-Arrays, nur numerische Arrays)
  • Slice (nur String-Arrays, Zahlenarrays)
  • Verkettung (nur Arrays von Strings, numerische Arrays)
  • Benutzerdefinierte Funktion: für die Schleife oder rekursive Kopie
  • jQuery $ .extend
  • JSON.parse (nur String-Arrays, Zahlenarrays, Arrays von Objekten)
  • Underscore.js _.clone (nur String-Arrays, numerische Arrays)
  • Lo-Dash _.cloneDeep

Kopieren Sie tief ein Array von Strings oder Zahlen (eine Ebene - keine Zeiger):

Wenn ein Array Zahlen und Strings enthält - Funktionen wie .slice (),. Concat (),. Splice (), der Zuweisungsoperator "=" und die Klonfunktion Underscore.js; Erstellen Sie eine tiefe Kopie der Elemente des Arrays.

Wenn die Neuzuweisung die höchste Leistung aufweist:

 var arr1 = ['a', 'b', 'c']; var arr2 = arr1; arr1 = ['a', 'b', 'c']; 

I.slice () hat eine bessere Leistung als .concat (), http://jsperf.com/duplicate-array-slice-vs-concat/3

 var arr1 = ['a', 'b', 'c']; // Becomes arr1 = ['a', 'b', 'c'] var arr2a = arr1.slice(0); // Becomes arr2a = ['a', 'b', 'c'] - deep copy var arr2b = arr1.concat(); // Becomes arr2b = ['a', 'b', 'c'] - deep copy 

Kopieren Sie tief ein Array von Objekten (zwei oder mehr Ebenen - Zeiger):

 var arr1 = [{object:'a'}, {object:'b'}]; 

Schreiben Sie eine benutzerdefinierte Funktion (hat eine bessere Leistung als $ .extend () oder JSON.parse):

 function copy(o) { var out, v, key; out = Array.isArray(o) ? [] : {}; for (key in o) { v = o[key]; out[key] = (typeof v === "object"  v !== null) ? copy(v) : v; } return out; } copy(arr1); 

Nutzen Sie die Funktionen anderer Anbieter:

 $.extend(true, [], arr1); // Jquery Extend JSON.parse(arr1); _.cloneDeep(arr1); // Lo-dash 

Wo jQuery $ .extend eine bessere Leistung bietet:

71
18 сент. Die Antwort wird im Monat 18 Sep. gegeben . 2014-09-18 23:10 '14 um 23:10 2014-09-18 23:10
 var clone = function() { var newObj = (this instanceof Array) ? [] : {}; for (var i in this) { if (this[i]  typeof this[i] == "object") { newObj[i] = this[i].clone(); } else { newObj[i] = this[i]; } } return newObj; }; Object.defineProperty( Object.prototype, "clone", {value: clone, enumerable: false}); 
60
26 дек. Die Antwort gibt Zibri am 26. Dezember. 2009-12-26 17:59 09 um 17:59 2009-12-26 17:59

Ich weiß, dass dies ein alter Beitrag ist, aber ich dachte, es könnte jemandem helfen, der stolpert.

So>

 var a = function(){ return { father:'zacharias' }; }, b = a(), c = a(); c.father = 'johndoe'; alert(b.father); 
53
24 сент. Antwort von Joe 24 Sep. 2011-09-24 22:28 '11 am 22:28 2011-09-24 22:28

Cloning Objekten war in JS schon immer ein Problem, aber es war alles vor ES6. Im Folgenden liste ich verschiedene Möglichkeiten auf, um ein Objekt in JavaScript zu kopieren. Stellen Sie sich vor, Sie haben unten ein Objekt und möchten eine tiefe Kopie davon haben:

 var obj = {a:1, b:2, c:3, d:4}; 

Es gibt mehrere Möglichkeiten, dieses Objekt zu kopieren, ohne die Quelle zu ändern:

1) ES5 + mit einer einfachen zu kopierenden Funktion:

 function deepCopyObj(obj) { if (null == obj || "object" != typeof obj) return obj; if (obj instanceof Date) { var copy = new Date(); copy.setTime(obj.getTime()); return copy; } if (obj instanceof Array) { var copy = []; for (var i = 0, len = obj.length; i < len; i++) { copy[i] = cloneSO(obj[i]); } return copy; } if (obj instanceof Object) { var copy = {}; for (var attr in obj) { if (obj.hasOwnProperty(attr)) copy[attr] = cloneSO(obj[attr]); } return copy; } throw new Error("Unable to copy obj this object."); } 

2) ES5 + mit JSON.parse und JSON.stringify.

 var deepCopyObj = JSON.parse(JSON.stringify(obj)); 

3) AngularJs:

 var deepCopyObj = angular.copy(obj); 

4) jQuery:

 var deepCopyObj = jQuery.extend(true, {}, obj); 

5) UnderscoreJs und Loadash:

 var deepCopyObj = _.cloneDeep(obj); //latest version UndescoreJs makes shallow copy 

Hoffe diese Hilfe ...

52
03 апр. Die Antwort wird gegeben Alireza 03 Apr. 2017-04-03 18:37 '17 um 18:37 Uhr 2017-04-03 18:37

Es gibt eine Bibliothek (genannt "Klon") , die es ziemlich gut macht. Es bietet das vollständigste rekursive Klonen / Kopieren von beliebigen Objekten, die mir bekannt sind. Es unterstützt auch zirkulare Links, die noch nicht von anderen Antworten abgedeckt werden.

Sie finden es auf npm . Es kann sowohl für den Browser als auch für Node.js verwendet werden.

Hier ist ein Beispiel, wie man es benutzt:

Installiere es mit

 npm install clone 

oder packe es mit Ender .

 ender build clone [...] 

Sie können den Quellcode auch manuell herunterladen.

Dann können Sie es in Ihrem Quellcode verwenden.

 var clone = require('clone'); var a = { foo: { bar: 'baz' } }; // inital value of a var b = clone(a); // clone a -> b a.foo.bar = 'foo'; // change a console.log(a); // { foo: { bar: 'foo' } } console.log(b); // { foo: { bar: 'baz' } } 

(Haftungsausschluss: Ich bin der Autor der Bibliothek.)

51
17 окт. Die Antwort ist pvorb 17 oct. 2012-10-17 21:36 '12 am 21:36 2012-10-17 21:36

Wenn Sie es verwenden, verfügt die Underscore.js- Bibliothek über einen Klon .

 var newObject = _.clone(oldObject); 
48
15 дек. die antwort wird von itsadok 15 dez. gegeben . 2011-12-15 18:56 '11 am 18:56 2011-12-15 18:56

Hier ist die obige Version von ConroyP, die auch dann funktioniert, wenn der Designer Parameter benötigt:

 //If Object.create isn't already defined, we just do the simple shim, //without the second argument, since that all we need here var object_create = Object.create; if (typeof object_create !== 'function') { object_create = function(o) { function F() {} F.prototype = o; return new F(); }; } function deepCopy(obj) { if(obj == null || typeof(obj) !== 'object'){ return obj; } //make sure the returned object has the same prototype as the original var ret = object_create(obj.constructor.prototype); for(var key in obj){ ret[key] = deepCopy(obj[key]); } return ret; } 

Diese Funktion ist auch in meiner simpleoo- Bibliothek verfügbar.

Bearbeiten:

Hier ist eine zuverlässigere Version (dank Justin McCandles, jetzt unterstützt er Zirkelverweise):

  function deepCopy(src,  _visited, _copiesVisited) { if(src === null || typeof(src) !== 'object'){ return src; } //Honor native/custom clone methods if(typeof src.clone == 'function'){ return src.clone(true); } //Special cases: //Date if(src instanceof Date){ return new Date(src.getTime()); } //RegExp if(src instanceof RegExp){ return new RegExp(src); } //DOM Element if(src.nodeType  typeof src.cloneNode == 'function'){ return src.cloneNode(true); } // Initialize the visited objects arrays if needed. // This is used to detect cyclic references. if (_visited === undefined){ _visited = []; _copiesVisited = []; } // Check if this object has already been visited var i, len = _visited.length; for (i = 0; i < len; i++) { // If so, get the copy we already made if (src === _visited[i]) { return _copiesVisited[i]; } } //Array if (Object.prototype.toString.call(src) == '[object Array]') { //[].slice() by itself would soft clone var ret = src.slice(); //add it to the visited array _visited.push(src); _copiesVisited.push(ret); var i = ret.length; while (i--) { ret[i] = deepCopy(ret[i], _visited, _copiesVisited); } return ret; } //If we've reached here, we have a regular object //make sure the returned object has the same prototype as the original var proto = (Object.getPrototypeOf ? Object.getPrototypeOf(src): src.__proto__); if (!proto) { proto = src.constructor.prototype; //this line would probably only be reached by very old browsers } var dest = object_create(proto); //add this object to the visited array _visited.push(src); _copiesVisited.push(dest); for (var key in src) { //Note: this does NOT preserve ES5 property attributes like 'writable', 'enumerable', etc. //For an example of how this could be modified to do so, see the singleMixin() function dest[key] = deepCopy(src[key], _visited, _copiesVisited); } return dest; } //If Object.create isn't already defined, we just do the simple shim, //without the second argument, since that all we need here var object_create = Object.create; if (typeof object_create !== 'function') { object_create = function(o) { function F() {} F.prototype = o; return new F(); }; } 
36
11 нояб. Die Antwort gibt Matt Browne vom 11. November. 2012-11-11 20:53 '12 um 20:53 Uhr 2012-11-11 20:53

Im Folgenden werden zwei Instanzen desselben Objekts erstellt. Ich habe es gefunden und benutze es jetzt. Es ist einfach und leicht zu bedienen.

 var objToCreate = JSON.parse(JSON.stringify(cloneThis)); 
31
21 авг. Antwort von Nathan Rogers 21. August 2015-08-21 18:51 '15 am 18:51 2015-08-21 18:51

Tiefes Kopieren von Objekten in Javascript (ich denke, das Beste und Einfachste)

1. JSON.parse verwenden (JSON.stringify (object));

 var obj = { a: 1, b: { c: 2 } } var newObj = JSON.parse(JSON.stringify(obj)); obj.bc = 20; console.log(obj); // { a: 1, b: { c: 20 } } console.log(newObj); // { a: 1, b: { c: 2 } } 

2. Verwenden Sie die erstellte Methode

 function cloneObject(obj) { var clone = {}; for(var i in obj) { if(obj[i] != null  typeof(obj[i])=="object") clone[i] = cloneObject(obj[i]); else clone[i] = obj[i]; } return clone; } var obj = { a: 1, b: { c: 2 } } var newObj = cloneObject(obj); obj.bc = 20; console.log(obj); // { a: 1, b: { c: 20 } } console.log(newObj); // { a: 1, b: { c: 2 } } 

3. Verwenden Sie Lo-Dash _.cloneDeep link lodash

 var obj = { a: 1, b: { c: 2 } } var newObj = _.cloneDeep(obj); obj.bc = 20; console.log(obj); // { a: 1, b: { c: 20 } } console.log(newObj); // { a: 1, b: { c: 2 } } 

4. Object.assign () verwenden

 var obj = { a: 1, b: 2 } var newObj = _.clone(obj); obj.b = 20; console.log(obj); // { a: 1, b: 20 } console.log(newObj); // { a: 1, b: 2 } 

ABER FALSCH, WANN

 var obj = { a: 1, b: { c: 2 } } var newObj = Object.assign({}, obj); obj.bc = 20; console.log(obj); // { a: 1, b: { c: 20 } } console.log(newObj); // { a: 1, b: { c: 20 } } --> WRONG // Note: Properties on the prototype chain and non-enumerable properties cannot be copied. 

5. Verwenden Sie Underscore.js _.clone link Underscore.js

 var obj = { a: 1, b: 2 } var newObj = _.clone(obj); obj.b = 20; console.log(obj); // { a: 1, b: 20 } console.log(newObj); // { a: 1, b: 2 } 

ABER FALSCH, WANN

 var obj = { a: 1, b: { c: 2 } } var newObj = _.cloneDeep(obj); obj.bc = 20; console.log(obj); // { a: 1, b: { c: 20 } } console.log(newObj); // { a: 1, b: { c: 20 } } --> WRONG // (Create a shallow-copied clone of the provided plain object. Any nested objects or arrays will be copied by reference, not duplicated.) 

Link medium.com

JSBEN.CH Performance Benchmarking Playground 1 ~ 3 http://jsben.ch/KVQLd 2019

08 авг. Die Antwort wird mit TinhNQ 08 gegeben. 2018-08-08 11:17 '18 at 11:17 ; 2018-08-08 11:17

Lodash hat eine gute Methode . cloneDeep (Wert) :

 var objects = [{ 'a': 1 }, { 'b': 2 }]; var deep = _.cloneDeep(objects); console.log(deep[0] === objects[0]); // => false 
23
22 июня '13 в 18:03 2013-06-22 18:03 Die Antwort wird von opensas am 22. Juni 13 um 18:03 2013-06-22 18:03 gegeben

Crockford schlägt vor (und ich bevorzuge), diese Funktion zu verwenden:

 function object(o) { function F() {} F.prototype = o; return new F(); } var newObject = object(oldObject); 

Es ist kurz, funktioniert wie erwartet und Sie benötigen keine Bibliothek.


BEARBEITEN:

Dies ist ein Polyfill für Object.create , Sie können es also auch verwenden.

 var newObject = Object.create(oldObject); 

HINWEIS. . Wenn Sie einige davon verwenden, können Probleme mit der Iteration auftreten, bei der hasOwnProperty verwendet hasOwnProperty . Denn create erstellt ein neues leeres Objekt, das oldObject erbt. Es ist jedoch immer noch nützlich und praktisch, um Objekte zu klonen.

Zum Beispiel, wenn oldObject.a = 5;

 newObject.a; // is 5 

a

 oldObject.hasOwnProperty(a); // is true newObject.hasOwnProperty(a); // is false 
23
06 окт. Antwort von Chris Broski 06. Oktober 2010-10-06 18:08 '10 um 18:08 2010-10-06 18:08
 function clone(obj) { var clone = {}; clone.prototype = obj.prototype; for (property in obj) clone[property] = obj[property]; return clone; } 
22
23 сент. Antwort von Mark Cidade am 23. September 2008-09-23 19:45 2008 um 19:45 Uhr 2008-09-23 19:45 Uhr

Einzeilige Kopie der flachen Kopie ( ECMAScript 5. Auflage ):

 var origin = { foo : {} }; var copy = Object.keys(origin).reduce(function(c,k){c[k]=origin[k];return c;},{}); console.log(origin, copy); console.log(origin == copy); // false console.log(origin.foo == copy.foo); // true 

Einzel- und kleines Exemplar ( ECMAScript 6. Ausgabe , 2015):

 var origin = { foo : {} }; var copy = Object.assign({}, origin); console.log(origin, copy); console.log(origin == copy); // false console.log(origin.foo == copy.foo); // true 
20
05 июля '12 в 0:44 2012-07-05 00:44 die antwort wird von maël nison am 5. juli 12 um 12:44 2012-07-05 00:44 gegeben

Nur weil ich AngularJS nicht gesehen habe und gedacht hätte, dass die Leute wissen wollen ...

angular.copy также предоставляет метод глубокого копирования объектов и массивов.

17
ответ дан Dan Atkinson 14 мая '16 в 1:16 2016-05-14 01:16

Кажется, что нет идеального оператора глубокого клонирования для объектов типа массива. Как видно из приведенного ниже кода, клонирующий JQuery John Resig превращает массивы с нечисловыми свойствами в объекты, которые не являются массивами, а клонирование RegDwight JSON отбрасывает нечисловые свойства. Следующие тесты иллюстрируют эти моменты в нескольких браузерах:

 function jQueryClone(obj) { return jQuery.extend(true, {}, obj) } function JSONClone(obj) { return JSON.parse(JSON.stringify(obj)) } var arrayLikeObj = [[1, "a", "b"], [2, "b", "a"]]; arrayLikeObj.names = ["m", "n", "o"]; var JSONCopy = JSONClone(arrayLikeObj); var jQueryCopy = jQueryClone(arrayLikeObj); alert("Is arrayLikeObj an array instance?" + (arrayLikeObj instanceof Array) + "\nIs the jQueryClone an array instance? " + (jQueryCopy instanceof Array) + "\nWhat are the arrayLikeObj names? " + arrayLikeObj.names + "\nAnd what are the JSONClone names? " + JSONCopy.names) 
16
ответ дан Page Notes 17 окт. '10 в 7:01 2010-10-17 07:01

У меня есть два хороших ответа в зависимости от того, должна ли ваша цель клонировать "простой старый объект JavaScript" или нет.

Предположим также, что вы намерены создать полный клон без ссылок на прототипы обратно к исходному объекту. Если вас не интересует полный клон, вы можете использовать многие из подпрограмм Object.clone(), предоставленные в некоторых других ответах (шаблон Crockford).

Для простых старых объектов JavaScript проверенный и правдивый способ клонирования объекта в современных условиях выполнения довольно просто:

 var clone = JSON.parse(JSON.stringify(obj)); 

Обратите внимание, что исходный объект должен быть чистым объектом JSON. Это означает, что все его вложенные свойства должны быть скалярами (например, логическими, строковыми, массивными, объектными и т.д.). Любые функции или специальные объекты, такие как RegExp или Date, не будут клонированы.

Это эффективно? Черт возьми. Мы пробовали все виды методов клонирования, и это работает лучше всего. Я уверен, что какой-нибудь ниндзя может вызвать более быстрый метод. Но я подозреваю, что мы говорим о предельных выигрышах.

Этот подход прост и прост в реализации. Оберните его в функцию удобства, и если вам действительно нужно выжать некоторый выигрыш, пойдите в более позднее время.

Теперь для не-простых объектов JavaScript нет простого ответа. На самом деле не может быть из-за динамического характера функций JavaScript и состояния внутреннего объекта. Глубокое клонирование структуры JSON с функциями внутри требует, чтобы вы воссоздали эти функции и их внутренний контекст. И JavaScript просто не имеет стандартного способа сделать это.

Правильный способ сделать это, опять же, с помощью метода удобства, который вы декларируете и повторно используете в своем коде. Метод удобства может быть наделен некоторым пониманием ваших собственных объектов, поэтому вы можете правильно воссоздать график в новом объекте.

Мы пишем наши собственные, но лучший общий подход, который я видел, рассматривается здесь:

http://davidwalsh.name/javascript-clone

Это правильная идея. Автор (Дэвид Уолш) прокомментировал клонирование обобщенных функций. Это то, что вы, возможно, захотите сделать, в зависимости от вашего варианта использования.

Основная идея заключается в том, что вам нужно специально обрабатывать создание ваших функций (или прототипных классов, если можно так выразиться) на основе каждого типа. Здесь он привел несколько примеров для RegExp и Date.

Это не только код, но и очень читаемый. Это довольно легко расширить.

Является ли это эффективным? Черт возьми. Учитывая, что цель состоит в том, чтобы создать настоящий клон с глубокой копией, вам придется ходить по членам графа исходного объекта. При таком подходе вы можете точно настроить, какие дочерние элементы обрабатывать и как вручную обрабатывать настраиваемые типы.

Итак, вы идете. Два подхода. На мой взгляд, обе эффективны.

15
ответ дан Michael Uzquiano 06 мая '13 в 23:45 2013-05-06 23:45

В Prototype вы сделаете что-то вроде

 newObject = Object.clone(myObject); 

Прототипная документация отмечает, что это делает мелкую копию.

14
ответ дан erlando 02 дек. '17 в 20:47 2017-12-02 20:47

Это не самое эффективное решение, но оно делает то, что мне нужно. Простые тестовые примеры ниже...

 function clone(obj, clones) { // Makes a deep copy of 'obj'. Handles cyclic structures by // tracking cloned obj in the 'clones' parameter. Functions // are included, but not cloned. Functions members are cloned. var new_obj, already_cloned, t = typeof obj, i = 0, l, pair; clones = clones || []; if (obj === null) { return obj; } if (t === "object" || t === "function") { // check to see if we've already cloned obj for (i = 0, l = clones.length; i < l; i++) { pair = clones[i]; if (pair[0] === obj) { already_cloned = pair[1]; break; } } if (already_cloned) { return already_cloned; } else { if (t === "object") { // create new object new_obj = new obj.constructor(); } else { // Just use functions as is new_obj = obj; } clones.push([obj, new_obj]); // keep track of objects we've cloned for (key in obj) { // clone object members if (obj.hasOwnProperty(key)) { new_obj[key] = clone(obj[key], clones); } } } } return new_obj || obj; } 

Тест циклического массива...

 a = [] a.push("b", "c", a) aa = clone(a) aa === a //=> false aa[2] === a //=> false aa[2] === a[2] //=> false aa[2] === aa //=> true 

Функциональный тест...

 f = new Function fa = a ff = clone(f) ff === f //=> true ff.a === a //=> false 
13
ответ дан neatonk 03 апр. '11 в 5:08 2011-04-03 05:08

AngularJS

Хорошо, если вы используете angular, вы тоже можете это сделать

 var newObject = angular.copy(oldObject); 
11
14 сент. Antwort von azerafati 14 sep . '16 в 16:26 2016-09-14 16:26
 // obj target object, vals source object var setVals = function (obj, vals) { if (obj  vals) { for (var x in vals) { if (vals.hasOwnProperty(x)) { if (obj[x]  typeof vals[x] === 'object') { obj[x] = setVals(obj[x], vals[x]); } else { obj[x] = vals[x]; } } } } return obj; }; 
10
ответ дан Dima 28 апр. '10 в 14:16 2010-04-28 14:16

Я не согласен с ответом с наибольшим количеством голосов здесь . Рекурсивный глубокий клон быстрее , чем упомянутый подход JSON.parse(JSON.stringify(obj)).

И здесь функция для быстрой справки:

 function cloneDeep (o) { let newO let i if (typeof o !== 'object') return o if (!o) return o if (Object.prototype.toString.apply(o) === '[object Array]') { newO = [] for (i = 0; i < o.length; i += 1) { newO[i] = cloneDeep(o[i]) } return newO } newO = {} for (i in o) { if (o.hasOwnProperty(i)) { newO[i] = cloneDeep(o[i]) } } return newO } 
10
ответ дан prograhammer 18 июня '17 в 9:34 2017-06-18 09:34

Вот комплексный метод clone(), который может клонировать любой объект JavaScript. Он обрабатывает почти все случаи:

 function clone(src, deep) { var toString = Object.prototype.toString; if (!src  typeof src != "object") { // Any non-object (Boolean, String, Number), null, undefined, NaN return src; } // Honor native/custom clone methods if (src.clone  toString.call(src.clone) == "[object Function]") { return src.clone(deep); } // DOM elements if (src.nodeType  toString.call(src.cloneNode) == "[object Function]") { return src.cloneNode(deep); } // Date if (toString.call(src) == "[object Date]") { return new Date(src.getTime()); } // RegExp if (toString.call(src) == "[object RegExp]") { return new RegExp(src); } // Function if (toString.call(src) == "[object Function]") { //Wrap in another method to make sure == is not true; //Note: Huge performance issue due to closures, comment this :) return (function(){ src.apply(this, arguments); }); } var ret, index; //Array if (toString.call(src) == "[object Array]") { //[].slice(0) would soft clone ret = src.slice(); if (deep) { index = ret.length; while (index--) { ret[index] = clone(ret[index], true); } } } //Object else { ret = src.constructor ? new src.constructor() : {}; for (var prop in src) { ret[prop] = deep ? clone(src[prop], true) : src[prop]; } } return ret; }; 
8
ответ дан user1547016 24 июля '12 в 0:39 2012-07-24 00:39
  • 1
  • 2
  • 3

Другие вопросы по меткам или Задайте вопрос