Das Googeln nach "Javascript-Klonobjekt" bringt einige wirklich seltsame Ergebnisse, einige sind hoffnungslos veraltet und andere einfach zu komplex, ist es nicht so einfach wie nur:
let clone = {...original};
Ist daran etwas falsch?
Das Googeln nach "Javascript-Klonobjekt" bringt einige wirklich seltsame Ergebnisse, einige sind hoffnungslos veraltet und andere einfach zu komplex, ist es nicht so einfach wie nur:
let clone = {...original};
Ist daran etwas falsch?
Antworten:
Dies ist gut für das flache Klonen . Die Objektverteilung ist ein Standardbestandteil von ECMAScript 2018 .
Für das Deep Cloning benötigen Sie eine andere Lösung .
const clone = {...original}
zu flachem Klon
const newobj = {...original, prop: newOne}
unveränderlich eine weitere Requisite zum Original hinzufügen und als neues Objekt speichern.
JSON.parse(JSON.stringify(input))
JSON.parse(JSON.stringify(input))
nicht, denn wenn es dort functions
oder infinity
als Werte vorhanden ist, wird es einfach null
an ihrer Stelle zugewiesen . Es wird nur funktionieren, wenn die Werte einfach sind literals
und nicht functions
.
BEARBEITEN: Als diese Antwort veröffentlicht wurde, war die {...obj}
Syntax in den meisten Browsern nicht verfügbar. Heutzutage sollten Sie damit einverstanden sein (es sei denn, Sie müssen IE 11 unterstützen).
Verwenden Sie Object.assign.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
Dies macht jedoch keinen tiefen Klon. Es gibt noch keine native Methode zum tiefen Klonen.
BEARBEITEN: Wie @Mike 'Pomax' Kamermans in den Kommentaren erwähnt hat, können Sie einfache Objekte (dh keine Prototypen, Funktionen oder Zirkelverweise) mit tief klonen JSON.parse(JSON.stringify(input))
JSON.parse(JSON.stringify(input))
handelt es sich um einen richtigen tiefen Klon. In dem Moment, in dem Prototypen, Funktionen oder Zirkelverweise im Spiel sind, funktioniert diese Lösung jedoch nicht mehr.
Wenn die von Ihnen verwendeten Methoden mit Objekten mit Datentypen wie Datum nicht gut funktionieren , versuchen Sie dies
Importieren _
import * as _ from 'lodash';
Tiefes Klonobjekt
myObjCopy = _.cloneDeep(myObj);
import _ from 'lodash';
ist ausreichend. Aber +1 für die Antwort "Rad nicht neu erfinden".
Wenn Sie json.parse (json.stringify (Objekt)) nicht verwenden möchten, können Sie rekursiv Schlüsselwertkopien erstellen:
function copy(item){
let result = null;
if(!item) return result;
if(Array.isArray(item)){
result = [];
item.forEach(element=>{
result.push(copy(element));
});
}
else if(item instanceof Object && !(item instanceof Function)){
result = {};
for(let key in item){
if(key){
result[key] = copy(item[key]);
}
}
}
return result || item;
}
Der beste Weg ist jedoch, eine Klasse zu erstellen, die einen Klon von sich selbst zurückgeben kann
class MyClass{
data = null;
constructor(values){ this.data = values }
toString(){ console.log("MyClass: "+this.data.toString(;) }
remove(id){ this.data = data.filter(d=>d.id!==id) }
clone(){ return new MyClass(this.data) }
}
Nach der Antwort von @marcel stellte ich fest, dass einige Funktionen des geklonten Objekts noch fehlten. z.B
function MyObject() {
var methodAValue = null,
methodBValue = null
Object.defineProperty(this, "methodA", {
get: function() { return methodAValue; },
set: function(value) {
methodAValue = value || {};
},
enumerable: true
});
Object.defineProperty(this, "methodB", {
get: function() { return methodAValue; },
set: function(value) {
methodAValue = value || {};
}
});
}
Wo auf MyObject konnte ich Methode A klonen, aber Methode B wurde ausgeschlossen. Dies geschah, weil es fehlt
enumerable: true
was bedeutete, dass es nicht in auftauchte
for(let key in item)
Stattdessen wechselte ich zu
Object.getOwnPropertyNames(item).forEach((key) => {
....
});
Dies beinhaltet nicht aufzählbare Schlüssel.
Ich fand auch, dass der Prototyp ( Proto ) nicht geklont wurde. Dafür habe ich letztendlich verwendet
if (obj.__proto__) {
copy.__proto__ = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
}
PS: Frustrierend, dass ich keine eingebaute Funktion dafür finden konnte.
Sie können es auch so machen,
let copiedData = JSON.parse(JSON.stringify(data));
We can do that with two way:
1- First create a new object and replicate the structure of the existing one by iterating
over its properties and copying them on the primitive level.
let user = {
name: "John",
age: 30
};
let clone = {}; // the new empty object
// let's copy all user properties into it
for (let key in user) {
clone[key] = user[key];
}
// now clone is a fully independant clone
clone.name = "Pete"; // changed the data in it
alert( user.name ); // still John in the original object
2- Second we can use the method Object.assign for that
let user = { name: "John" };
let permissions1 = { canView: true };
let permissions2 = { canEdit: true };
// copies all properties from permissions1 and permissions2 into user
Object.assign(user, permissions1, permissions2);
-Another example
let user = {
name: "John",
age: 30
};
let clone = Object.assign({}, user);
It copies all properties of user into the empty object and returns it. Actually, the same as the loop, but shorter.
Object.assign () erstellt jedoch keinen tiefen Klon
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
let clone = Object.assign({}, user);
alert( user.sizes === clone.sizes ); // true, same object
// user and clone share sizes
user.sizes.width++; // change a property from one place
alert(clone.sizes.width); // 51, see the result from the other one
Um dies zu beheben, sollten wir die Klonschleife verwenden, die jeden Wert von Benutzer [Schlüssel] untersucht und, wenn es sich um ein Objekt handelt, auch dessen Struktur repliziert. Das nennt man ein "tiefes Klonen".
Es gibt einen Standardalgorithmus für das tiefe Klonen, der den obigen Fall und komplexere Fälle behandelt, den strukturierten Klonalgorithmus . Um das Rad nicht neu zu erfinden, können wir eine funktionierende Implementierung aus der JavaScript-Bibliothek lodash verwenden. Die Methode heißt _.cloneDeep (obj) .
Alle oben genannten Methoden behandeln nicht das tiefe Klonen von Objekten, bei denen es auf n Ebenen verschachtelt ist. Ich habe die Leistung nicht gegenüber anderen überprüft, aber sie ist kurz und einfach.
Das erste Beispiel unten zeigt Object.assign
das Klonen von Objekten, mit denen Klone bis zur ersten Ebene geklont werden.
var person = {
name:'saksham',
age:22,
skills: {
lang:'javascript',
experience:5
}
}
newPerson = Object.assign({},person);
newPerson.skills.lang = 'angular';
console.log(newPerson.skills.lang); //logs Angular
Mit dem folgenden Ansatz klonen tiefe Objekte
var person = {
name:'saksham',
age:22,
skills: {
lang:'javascript',
experience:5
}
}
anotherNewPerson = JSON.parse(JSON.stringify(person));
anotherNewPerson.skills.lang = 'angular';
console.log(person.skills.lang); //logs javascript
original = { a: [1,2,3] }
gibt Ihnen einen Klon mitclone.a
buchstäblich Seinoriginal.a
. Modifikation durch entwederclone
oderoriginal
modifiziert dasselbe , also nein, das ist schlecht =)