So verketten Sie Eigenschaften aus mehreren JavaScript-Objekten

105

Ich suche nach dem besten Weg, um mehrere JavaScript-Objekte (assoziative Arrays) "hinzuzufügen".

Zum Beispiel gegeben:

a = { "one" : 1, "two" : 2 };
b = { "three" : 3 };
c = { "four" : 4, "five" : 5 };

Was ist der beste Weg, um zu berechnen:

{ "one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }
Vlad
quelle
3
Eine semantische Anmerkung: Trotz der [] -Syntax sind sie überhaupt keine Arrays. Bestellung ist nicht wirklich garantiert.
Álvaro González
1
Die Iterationsreihenfolge kann nicht gemäß den Ecma-Standards garantiert werden. Aber es ist die Art und Weise, wie es in den meisten Browsern implementiert ist. (Von John Resig) Dieses Verhalten wird in der ECMAScript-Spezifikation explizit nicht definiert. In ECMA-262, Abschnitt 12.6.4: Die Mechanik der Aufzählung der Eigenschaften ... ist implementierungsabhängig. Die Spezifikation unterscheidet sich jedoch erheblich von der Implementierung. Alle modernen Implementierungen von ECMAScript durchlaufen die Objekteigenschaften in der Reihenfolge, in der sie definiert wurden. Aus diesem Grund hat das Chrome-Team dies als Fehler eingestuft und wird es beheben.
Juan Mendes

Antworten:

158

ECMAscript 6 wurde eingeführt Object.assign(), um dies nativ in Javascript zu erreichen.

Die Object.assign () -Methode wird verwendet, um die Werte aller aufzählbaren eigenen Eigenschaften von einem oder mehreren Quellobjekten in ein Zielobjekt zu kopieren. Das Zielobjekt wird zurückgegeben.

MDN-Dokumentation zu Object.assign ()

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }

Object.assignwird in vielen modernen Browsern unterstützt, aber noch nicht in allen. Verwenden Sie einen Transpiler wie Babel und Traceur , um abwärtskompatibles ES5-JavaScript zu generieren.

Filoxo
quelle
4
Dies ist eines der besten, die ich sagen kann. Da E6 jetzt hauptsächlich verwendet wird, ist Object.assign die beste Antwort.
Vimalraj Selvam
6
Wenn Sie nicht wissen, wie viele Objekte zusammengeführt werden müssen, können Sie sie wie folgt zusammenführen, da sie sich in einem Array befinden:Object.assign.apply({}, [{a: 1}, {b: 2}, ....])
Jeanluca Scaljeri
Eine Alternative zum Object.assign.applyZusammenführen eines Arrays von Objekten besteht darin, stattdessen den Spread-Operator zu verwenden:Object.assign( ...objects )
Spen
@Spen, das bereits als Antwort auf diese Frage enthalten ist. Ich habe keinen Vorteil darin gesehen, es hier zu duplizieren.
Filoxo
Nach 4 Stunden löste diese Antwort mein Problem in Angular 7. Vielen Dank für die Einfachheit und Genauigkeit der Antwort.
Gel
35

Sie könnten jquery's $.extendwie folgt verwenden :

let a = { "one" : 1, "two" : 2 },
    b = { "three" : 3 },
    c = { "four" : 4, "five" : 5 };

let d = $.extend({}, a, b, c)

console.log(d)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

adiga
quelle
+1 Auch wenn Sie die Methode von jQuery nicht verwenden, können Sie deren Code verwenden, um Ihre eigene (möglicherweise spezifischere) Implementierung zu erstellen.
Tvanfosson
25
@Randal: Es gibt viele gute Gründe, jQuery nicht zu verwenden.
Tim Down
3
Bearbeiten:d = $.extend({},a,b,c);
Bob Stein
34

Dies sollte es tun:

function collect() {
  var ret = {};
  var len = arguments.length;
  for (var i = 0; i < len; i++) {
    for (p in arguments[i]) {
      if (arguments[i].hasOwnProperty(p)) {
        ret[p] = arguments[i][p];
      }
    }
  }
  return ret;
}

let a = { "one" : 1, "two" : 2 };
let b = { "three" : 3 };
let c = { "four" : 4, "five" : 5 };

let d = collect(a, b, c);
console.log(d);

Ausgabe:

{
  "one": 1,
  "two": 2,
  "three": 3,
  "four": 4,
  "five": 5
}
Cletus
quelle
Nicht lengthNachschlag die Größe des Arrays bei jedem Aufruf? Ich bin es so gewohnt zu schreiben, for (var i = 0, len = array.length; i < len; ++i)dass ich mich nicht mehr daran erinnern kann, warum ich damit angefangen habe.
Tvanfosson
1
Ja das ist richtig. Es ist besser, die Länge einmal zwischenzuspeichern. Da die Größe der Argumente "Array" jedoch wahrscheinlich nie sehr groß sein wird, spielt dies in diesem Fall keine Rolle.
Jhurshman
1
Nein, außer leicht auf IE6. Der Zugriff auf die Eigenschaft length kostet genauso viel wie der Zugriff auf die Variable len.
Alsciende
1
@ Juan Ich glaube, Sie sind falsch, und ich habe einige Tests durchgeführt, um mich zu entscheiden. Das Zwischenspeichern der Länge ist ein einfacher Mythos der Optimierung, der seit vielen Jahren veraltet ist und den Code (etwas) weniger lesbar macht. Tatsächlich verlangsamt das Zwischenspeichern der Länge manchmal den Browser (Safari).
Alsciende
2
Wäre es nicht besser, "für (var p in ..." anstelle von "für (p in ...") zu schreiben?
Hugo
24

ECMAScript 6 hat eine verbreitete Syntax . Und jetzt können Sie dies tun:

const obj1 = { 1: 11, 2: 22 };
const obj2 = { 3: 33, 4: 44 };
const obj3 = { ...obj1, ...obj2 };

console.log(obj3); // {1: 11, 2: 22, 3: 33, 4: 44}

Valex
quelle
12

Unterstreichen hat nur wenige Methoden, um dies zu tun;

1. _.extend (Ziel, * Quellen)

Kopieren Sie alle Eigenschaften in der Quelle über zu den Objekten Zielobjekt, und senden Sie das Zielobjekt.

_.extend(a, _.extend(b, c));
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

Oder

_.extend(a, b);
=> {"one" : 1, "two" : 2, "three" : 3}
_.extend(a, c);
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

2. _.defaults (Objekt, * Standard)

Füllen Sie undefinierte Eigenschaften im Objekt mit Werten aus den Standardobjekten aus und geben Sie das Objekt zurück .

_.defaults(a, _.defaults(b, c));
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

Oder

_.defaults(a, b);
=> {"one" : 1, "two" : 2, "three" : 3}
_.defaults(a, c);
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }
Gihanchanuka
quelle
4

Warum sollte die Funktion auf 3 Argumente beschränkt sein? Überprüfen Sie auch für hasOwnProperty.

function Collect() {
    var o={};
    for(var i=0;i<arguments.length;i++) {
      var arg=arguments[i];
      if(typeof arg != "object") continue;
      for(var p in arg) {
        if(arg.hasOwnProperty(p)) o[p] = arg[p];
      }
    }
    return o;
}
Alsciende
quelle
4

Flaches Klonen (ohne Prototyp) oder Zusammenführen von Objekten ist jetzt mit einer kürzeren Syntax als Object.assign () möglich .

Die Spread-Syntax für Objektliterale wurde in ECMAScript 2018 eingeführt :

const a = { "one": 1, "two": 2 };
const b = { "three": 3 };
const c = { "four": 4, "five": 5 };

const result = {...a, ...b, ...c};
// Object { "one": 1, "two": 2 , "three": 3, "four": 4, "five": 5 }

Der Spread (...) -Operator wird in vielen modernen Browsern unterstützt, jedoch nicht in allen.

Es wird daher empfohlen, einen Transpiler wie Babel zu verwenden zu verwenden, um ECMAScript 2015+ Code in aktuellen und älteren Browsern oder Umgebungen in eine abwärtskompatible Version von JavaScript zu konvertieren.

Dies ist der entsprechende Code, den Babel für Sie generiert :

"use strict";

var _extends = Object.assign || function(target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i];
    for (var key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        target[key] = source[key];
      }
    }
  }
  return target;
};

var a = { "one": 1, "two": 2 };
var b = { "three": 3 };
var c = { "four": 4, "five": 5 };

var result = _extends({}, a, b, c);
// Object { "one": 1, "two": 2 , "three": 3, "four": 4, "five": 5 }
Thiago Santos
quelle
Dies ist eine viel robustere Antwort als die akzeptierte Antwort. Vielen Dank!
Kaleb Anderson
3
function Collect(a, b, c) {
    for (property in b)
        a[property] = b[property];

    for (property in c)
        a[property] = c[property];

    return a;
}

Hinweis: Vorhandene Eigenschaften in vorherigen Objekten werden überschrieben.

Björn
quelle
2
Dies hat den Nebeneffekt, dass a === dam Ende. Das könnte in Ordnung sein und es könnte nicht.
Tvanfosson
2

Es ist einfach, den ES7-Spread-Operator für ein Objekt in Ihrer Browserkonsole zu verwenden

({ name: "Alex", ...(true  ? { age: 19 } : { })}) // {name: "Alex", age: 19}
({ name: "Alex", ...(false ? { age: 19 } : { })}) // {name: "Alex",        }
Purkhalo Alex
quelle
1
Nett. Diese Frage ist mehr als 10 Jahre alt und froh, dass diese einfache Bedienung jetzt einfach ist. Es war vorher nicht so einfach, wenn man sich die Antworten der anderen Leute ansieht.
Vlad
Deshalb habe ich meine eigene Antwort
hinterlassen
1

Der schnellste, effizienteste und allgemeinere Weg ist wahrscheinlich dieser (Sie können eine beliebige Anzahl von Objekten zusammenführen und sogar auf den ersten kopieren -> zuweisen):

function object_merge(){
    for (var i=1; i<arguments.length; i++)
       for (var a in arguments[i])
         arguments[0][a] = arguments[i][a];
   return arguments[0];
}

Außerdem können Sie das erste Objekt so ändern, wie es als Referenz übergeben wurde. Wenn Sie dies nicht möchten, aber ein völlig neues Objekt mit allen Eigenschaften haben möchten, können Sie {} als erstes Argument übergeben.

var object1={a:1,b:2};
var object2={c:3,d:4};
var object3={d:5,e:6};
var combined_object=object_merge(object1,object2,object3); 

Das kombinierte Objekt und das Objekt1 enthalten beide die Eigenschaften von Objekt1, Objekt2, Objekt3.

var object1={a:1,b:2};
var object2={c:3,d:4};
var object3={d:5,e:6};
var combined_object=object_merge({},object1,object2,object3); 

In diesem Fall enthält das kombinierte Objekt die Eigenschaften von Objekt1, Objekt2, Objekt3, aber Objekt1 wird nicht geändert.

Überprüfen Sie hier: https://jsfiddle.net/ppwovxey/1/

Hinweis: JavaScript-Objekte werden als Referenz übergeben.

Selay
quelle
1

ES6 ++

Die Frage ist das Hinzufügen von verschiedenen unterschiedlichen Objekten in einem.

let obj = {};
const obj1 = { foo: 'bar' };
const obj2 = { bar: 'foo' };
Object.assign(obj, obj1, obj2);
//output => {foo: 'bar', bar: 'foo'};

Angenommen, Sie haben ein Objekt mit mehreren Schlüsseln, die Objekte sind:

let obj = {
  foo: { bar: 'foo' },
  bar: { foo: 'bar' }
}

Dies war die Lösung, die ich gefunden habe (muss noch vorgehen: /)

let objAll = {};

Object.values(obj).forEach(o => {
  objAll = {...objAll, ...o};
});

Auf diese Weise können wir ALLE Objektschlüssel dynamisch zu einem hinzufügen.

// Output => { bar: 'foo', foo: 'bar' }
Joseph Briggs
quelle
1

Um eine dynamische Anzahl von Objekten zusammenführen, können wir verwenden , Object.assignmit Spread - Syntax .

const mergeObjs = (...objs) => Object.assign({}, ...objs);

Die obige Funktion akzeptiert eine beliebige Anzahl von Objekten und führt alle ihre Eigenschaften zu einem neuen Objekt zusammen, wobei Eigenschaften von späteren Objekten diejenigen von vorherigen Objekten überschreiben.

Demo:

Um ein Array von Objekten zusammenzuführen, kann eine ähnliche Methode angewendet werden.

const mergeArrayOfObjs = arr => Object.assign({}, ...arr);

Demo:

hev1
quelle
0

Am einfachsten: Operatoren verbreiten

var obj1 = {a: 1}
var obj2 = {b: 2}
var concat = { ...obj1, ...obj2 } // { a: 1, b: 2 }
Rodolfo Paranhos
quelle
-2
function collect(a, b, c){
    var d = {};

    for(p in a){
        d[p] = a[p];
    }
    for(p in b){
        d[p] = b[p];
    }
    for(p in c){
        d[p] = c[p];
    }

    return d;
}
Álvaro González
quelle