Wie dupliziere ich Objekteigenschaften in einem anderen Objekt?

184

Angesichts des Objekts:

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

Wie kann ich die Eigenschaften in ein anderes Objekt ( secondObject) wie folgt kopieren :

var secondObject = {
    key1 : 'value1',
    key2 : 'value2',
    key3 : 'value3',
    key4 : 'value4'
};

mit einem Verweis auf die firstObject? Etwas wie das:

var secondObject = {
    firstObject,
    key3 : 'value3',
    key4 : 'value4'
};

(Das funktioniert nicht ... Ich habe es nur in großen Zeilen dargestellt, um zu zeigen, wie ich den Code strukturieren möchte.)

Ist eine Lösung ohne Verwendung von JavaScript-Frameworks möglich?

Igor Popov
quelle
3
Hier beantwortet: stackoverflow.com/questions/171251/…
Calvin
1
Die Frage ist, möchten Sie eine flache oder eine tiefe Kopie? Wenn tief, wie tief?
Georg
5
FWIW, sie werden "Eigenschaften" genannt, nicht "Attribute".
TJ Crowder
Hier ist etwas wirklich Hässliches, das trotzdem funktioniert (nicht wirklich empfohlen! Nur ein einzeiliger Proof-of-Concept):secondObject = JSON.parse('{' + JSON.stringify(firstObject).match(/^.(.*).$/)[1] + ',' + JSON.stringify(secondObject).match(/^.(.*).$/)[1] + '}');
Ben Lee
@TJCrowder: Ich habe die Frage korrigiert ... danke.
Igor Popov

Antworten:

213
for(var k in firstObject) secondObject[k]=firstObject[k];
Michael Krelin - Hacker
quelle
3
@ BenLee, was Sie hier vermissen, ist, dass Igor die genaue Verwendung gezeigt hat, die er dafür hat, in der hasOwnPropertyes nutzlos ist. Während ich Ihren Zeiger nützlich finden, halte ich die Idee der Anwendung irgendwelche Regeln zu jeder Situation schädlich und unklug. Wie all diese mustergetriebenen Entwicklungspraktiken, die derzeit stattfinden, nehmen Sie es nicht persönlich ...
Michael Krelin - Hacker
1
@ MichaelKrelin-Hacker, was Sie hier vermissen, ist, dass StackOverflow nicht nur zum Nutzen des OP ist. Es ist , als Referenz für zukünftige Besucher verwendet , die leicht unterschiedliche Anwendungsfälle haben kann, wo dieser Zeiger kann nützlich sein.
Ben Lee
@BenLee, ich bin nicht IgorPopov ;-) Und da ich nicht der OP bin, habe ich bereits gesagt, dass ich den Zeiger nützlich finde und Ihre Antwort auch, es ist der Teil "Sie sollten wirklich verwenden", den ich nicht mag.
Michael Krelin - Hacker
23
Sie lassen einen hasOwnProperty()Test aus und die Dinge funktionieren irgendwie weiter. Bis sie aufhören, weil Ihre Objekte im Laufe der Zeit komplexer wurden. Außer dann bricht es auf mysteriöse Weise in einem nicht verwandten Teil des Codes, weil zu viel kopiert wurde. Und Sie haben keinen Kontext zum Debuggen. JS ist so beschissen, daher ist eine sorgfältige Codierung, um das Auftreten solcher Probleme zu verhindern, umsichtig.
Eli Bendersky
2
Ich denke, diese Antwort muss gemäß dem folgenden Link aktualisiert werden: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… const target = {a: 1, b: 2}; const source = {b: 4, c: 5}; const returnTarget = Object.assign (Ziel, Quelle); console.log (Ziel); // erwartete Ausgabe: Objekt {a: 1, b: 4, c: 5} console.log (returnTarget); // erwartete Ausgabe: Objekt {a: 1, b: 4, c: 5}
Elbassel
170

Ausgehend von der Antwort von @ Bardzuśny hat ES6 eine native Lösung geliefert: die Object.assign()Funktion!

Die Verwendung ist einfach:

Object.assign(secondObject, firstObject);

Das ist es!

Die Unterstützung ist derzeit offensichtlich schlecht. Nur Firefox (34+) unterstützt es sofort, während Chrome (45+) und Opera (32+) das Setzen des 'experimentellen Flags' erfordern.

Die Unterstützung wird verbessert, wobei die neuesten Versionen von Chrome, Firefox, Opera, Safari und Edge dies unterstützen (IE hat insbesondere keine Unterstützung). Transpiler wie Babel und Traceur sind ebenfalls verfügbar. Sehen Sie hier für weitere Details.

Der DIMM Reaper
quelle
4
+1, eine weitere coole ES6-Funktion. Natürlich fehlt die Unterstützung für Browser / sogar Node.JS vorerst, aber wie Sie bereits erwähnt haben, sind Transpiler verfügbar. Und wenn Sie sie nicht mögen - Shims: github.com/paulmillr/es6-shim (oder Standalone, Object.assign()-nur Shim: github.com/ljharb/object.assign ).
Bardzusny
1
@Xoyce Wenn Sie die verknüpfte MDN-Seite überprüfen, wird deutlich angegeben: "Wenn der Quellwert eine Referenz auf ein Objekt ist, wird nur dieser Referenzwert kopiert." Es behält also tatsächlich die Referenz bei und kopiert das Objekt nicht. Ihre Warnung vor unerwartetem Verhalten ist immer noch zutreffend und es kommt darauf an, die richtigen Erwartungen zu haben.
Der DIMM Reaper
@mostafiz Ich habe Ihre Bearbeitung zurückgesetzt, da die Frage und andere Antworten auf dieser Seite die Namen "firstObject" und "secondObject" verwenden. Aus Gründen der Klarheit und Konsistenz habe ich hier dieselben Namen verwendet.
Der DIMM Reaper
Wenn dies mit der Frage übereinstimmt, ist es in Ordnung.
Mostafiz Rahman
1
@pdem Ja - siehe die Antwort von kingPuppy .
Der DIMM Reaper
100

Per ES6 - Spread-Syntax :

Sie können einfach verwenden:

const thirdObject = {
   ...firstObject,
   ...secondObject   
}

Dies vermeidet Probleme beim Übergeben dieser Objekte als Referenz.

Zusätzlich werden Objekte mit tiefer Verschachtelung behandelt.

kingPuppy
quelle
2
Wow, das ist wirklich großartig :) Danke für die Antwort. Natürlich brauche ich es nicht mehr (seit einiger Zeit), aber es könnte jemand anderem helfen.
Igor Popov
1
+1 für eine noch coolere Nutzung von ES6! In den oben genannten MDN-Dokumenten wird die Verwendung des Spread-Operators für Objekte nicht erwähnt. Daher habe
The DIMM Reaper
1
@jaepage - guter Kommentar als Referenz. Ein Objekt (gemäß der ursprünglichen Frage) mit einfachen Eigenschaftsnamen ist iterierbar.
kingPuppy
1
Funktioniert in Chrome, dies ist ES6, Sie benötigen derzeit Babel oder einen ES6-Transpiler. In Zukunft wird erwartet, dass alle Browser diese Syntax unterstützen.
kingPuppy
89

Durchlaufen Sie die Eigenschaften des ersten Objekts und weisen Sie sie dem zweiten Objekt wie folgt zu:

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject = {
    key3 : 'value3',
    key4 : 'value4'
};

for (var prop in firstObject) {
    if (firstObject.hasOwnProperty(prop)) {
        secondObject[prop] = firstObject[prop];
    }
}

Die for- inSchleife ist nicht genug; du brauchst hasOwnProperty. Unter http://bonsaiden.github.com/JavaScript-Garden/#object.forinloop finden Sie eine ausführliche Erklärung, warum.

Ben Lee
quelle
@RobW, ich hätte nicht gedacht, dass das OP referenceim technischen Sinne verwendet. Ich denke, er meint nur natürliche Sprache "beziehen auf".
Ben Lee
1
@RobW: Das OP hat tatsächlich "Kopie" gesagt.
TJ Crowder
49

Hier den Nekromanten spielen, weil ES5 uns gebracht hat Object.keys(), mit dem Potenzial, uns vor all diesen .hasOwnProperty()Prüfungen zu retten .

Object.keys(firstObject).forEach(function(key) {
  secondObject[key] = firstObject[key];
});

Oder wickeln Sie es in eine Funktion ein (begrenzte "Kopie" von lodash _.assign()):

function assign(object, source) {
  Object.keys(source).forEach(function(key) {
    object[key] = source[key];
  });
}

assign(secondObject, firstObject); // assign firstObject properties to secondObject

Object.keys()ist eine relativ neue Methode, vor allem: nicht verfügbar in IE <9. Das gleiche gilt für die .forEach()Array-Methode, die ich anstelle der regulären forSchleife verwendet habe.

Glücklicherweise gibt es für diese alten Browser es5-shim , das viele ES5-Funktionen (einschließlich dieser beiden) mehrfach ausfüllt.

(Ich bin alles für Polyfills, anstatt mich von der Verwendung cooler, neuer Sprachfunktionen zurückzuhalten.)

bardzusny
quelle
Plötzlich 2 Downvotes aus dem Nichts. Mit geringer Wahrscheinlichkeit, dass diese Jungs diesen Kommentar lesen - was ist der eigentliche Grund für sie? Was würden Sie vorschlagen, um meine Antwort zu ändern / zu verbessern?
Bardzusny
1
Dies verdient es definitiv, nach oben zu steigen, ebenso wie der Objektverteilungsinitialisierer weiter unten (ES6) - dies sieht mit Pfeilfunktionen noch sauberer aus!
Mjohnsonengr
12

Necro'ing, damit Benutzer mit hasOwnProperty und der tatsächlichen Objektprüfung eine Deep-Copy-Methode finden können:

var extend = function (original, context, key) {
  for (key in context)
    if (context.hasOwnProperty(key))
      if (Object.prototype.toString.call(context[key]) === '[object Object]')
        original[key] = extend(original[key] || {}, context[key]);
      else
        original[key] = context[key];
  return original;
};
Nijikokun
quelle
Beachten Sie, dass dies keine Arrays oder Funktionsobjekte tief kopiert (aber alle anderen Arten von Objekten tief kopiert).
Matt Browne
1
Ja, wenn Sie Arrays tief kopieren möchten, ändern Sie einfach die Typprüfung so, dass sie enthält'[object Array]'
Nijikokun
12

Man kann Object.assign verwenden , um Objekte zu kombinieren. Die gemeinsame Eigenschaft wird von rechts nach links kombiniert und überschrieben, dh dieselbe Eigenschaft links wird von rechts überschrieben.

Und es ist wichtig , im ersten ein leeres Objekt anzugeben, um eine Mutation der Quellobjekte zu vermeiden. Die Quellobjekte sollten sauber bleiben, da sie Object.assign()selbst ein neues Objekt zurückgeben.

Hoffe das hilft!

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject = {
    key3 : 'value3',
    key4 : 'value4'
};

var finalObject = Object.assign({}, firstObject, secondObject)

console.log(finalObject)

Pranesh Ravi
quelle
aber was ist, wenn Sie möchten, dass es das erste Objekt mutiert? Sie haben Objekt A und Objekt B und möchten, dass es Objekt A so mutiert, dass alle Eigenschaften den Eigenschaften von Objekt B entsprechen. Würden Sie Object.assign (A, B) ausführen?
TKoL
Leider nicht auf IE, Android WebView, Android Opera gemäß dieser Mozilla Developer Network-Seite unterstützt.
Yetti99
6

Verbesserung der kingPuppy- Idee und der OP-Idee (flache Kopie) - Ich füge nur 3 Punkte zum OP "Beispiel" hinzu :)

var secondObject = {
    ...firstObject,
    key3 : 'value3',
    key4 : 'value4'
};

Kamil Kiełczewski
quelle
4

Dies sollte funktionieren, hier getestet .

var secondObject = {
    firstObject: JSON.parse(JSON.stringify(firstObject)),
    key3 : 'value3',
    key4 : 'value4'
};

Hinweis : Dadurch werden die Methoden von firstObject
Hinweis 2 nicht kopiert. Für die Verwendung in älteren Browsern benötigen Sie einen JSON-Parser.
Hinweis 3 : Die Zuweisung per Referenz ist eine praktikable Option, insbesondere wenn sie firstObjectMethoden enthält. Das angegebene jsfiddle-Beispiel wurde entsprechend angepasst

KooiInc
quelle
3

Leider können Sie in einem solchen Objekt keinen Verweis auf eine Variable einfügen. Sie können jedoch eine Funktion erstellen, die die Werte des Objekts in ein anderes Objekt kopiert.

function extend( obj1, obj2 ) {
    for ( var i in obj2 ) {
        obj1[i] = obj2[i];
    }
    return obj1;
}

var firstObject = {
    key1: "value1",
    key2: "value2"
};

var secondObject = extend({
    key3: "value3",
    key4: "value4"
}, firstObject );
Wille
quelle
Dadurch werden auch native Eigenschaften kopiert. Und wie wäre es mit Eigenschaften, die selbst Objekte sind?
KooiInc
1

Wenn Sie nur die Eigenschaften abrufen möchten, die im zweiten Objekt vorhanden sind, können Sie Object.keysdie Eigenschaften des ersten Objekts abrufen. Sie haben zwei Methoden:

A.) map um die Eigenschaften des ersten Objekts dem zweiten Objekt unter Verwendung von Nebenwirkungen zuzuweisen:

var a = {a:100, b:9000, c:300};
var b = {b:-1};

Object.keys(a).map(function(key, index) {
    if (typeof b[key] !== 'undefined') {
        console.log(key);
        b[key] = a[key];    
    }
});

B.) oder reduceum ein neues Objekt zu erstellen und es dem zweiten Objekt zuzuweisen. Bitte beachten Sie, dass diese Methode ersetzt andere Eigenschaften das zweite Objekt davor haben könnte , die nicht das erste Objekt brachte:

var a = {a:100, b:9000, c:300};
var b = {b:-1, d:-1}; // d will be gone

b = Object.keys(a).reduce(function(result, current) {
    if (typeof b[current] !== 'undefined') {
        result[current] = a[current];   
    }
    return result;
}, {});
apebeast
quelle
1

Verwenden Sie die Eigenschaftsverbreitungsnotation. Es wurde in ES2018 hinzugefügt (Spread für Arrays / Iterables war früher, ES2015). {... firstObject} verteilt alle aufzählbaren Eigenschaften als diskrete Eigenschaften.

let secondObject = {
      ...firstObject,
      key3 : 'value3',
      key4 : 'value4'
    }
Anthony Awuley
quelle
Können Sie bitte einen Kontext zu Ihrer Antwort geben und warum sie die vorliegende Frage löst
Tamir Klein
0

Ich würde lieber firstObject als Prototyp von secondObject verwenden und einen Eigenschaftsdeskriptor hinzufügen:

var secondObject = Object.create(firstObject, {
      key3: {value: "value3", writable: true, configurable: true, enumerable: true},
      key4: {value: "value4", writable: true, configurable: true, enumerable: true}
      });

Es ist sicherlich kein Einzeiler, aber es gibt Ihnen mehr Kontrolle. Wenn Sie an Eigenschaftsbeschreibungen interessiert sind, empfehle ich, diesen Artikel zu lesen: http://patrickdelancy.com/2012/09/property-descriptors-in-javascript/#comment-2062 und MDN-Seite https: //developer.mozilla. org / de-US / docs / Web / JavaScript / Reference / Global_Objects / Object / create

Sie können auch einfach Werte zuweisen und die Deskriptoren weglassen und etwas kürzer machen:

var secondObject = Object.create(firstObject, {
      key3: {value: "value3"}
      key4: {value: "value4"}
  });

Kompatibilität: ECMAScript 5, also IE9 +

Ahmet Cetin
quelle
0
var firstObject = {
     key1: "value1",
     key2: "value2"
};

var secondObject = {
     key3: "value3",
     key4: "value4"
     copy: function(firstObject){
           this.key1 = firstObject.key1;
           this.key2 = firstObject.key2;
     }
 };

Mit der folgenden Methode werden die Eigenschaften kopiert

secondObject.copy(firstObject)

Ich bin sehr neu in Javascript, fand aber, dass dies funktioniert. Ein bisschen zu lang, denke ich, aber es funktioniert.

Sindhu Tirth
quelle