3287 Stimmen

Wie kann ich die Eigenschaften von zwei JavaScript-Objekten dynamisch zusammenführen?

Ich muss in der Lage sein, zwei (sehr einfache) JavaScript-Objekte zur Laufzeit zu verschmelzen. Zum Beispiel würde ich gerne:

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }

obj1.merge(obj2);

//obj1 now has three properties: food, car, and animal

Gibt es eine eingebaute Möglichkeit, dies zu tun? Ich brauche keine Rekursion, und ich muss nicht Funktionen zusammenführen, nur Methoden auf flache Objekte.

0 Stimmen

Es ist erwähnenswert diese Antwort auf eine ähnliche Frage , die zeigt, wie man "eine Ebene tiefer" zusammenführt. Das heißt, es werden Werte mit doppelten Schlüsseln zusammengeführt (anstatt den ersten Wert mit dem zweiten zu überschreiben), aber es wird nicht weiter rekursiert als das. IMHO ist es ein guter, sauberer Code für diese Aufgabe.

0 Stimmen

Übrigens führen die ersten paar Antworten eine "oberflächliche" Zusammenführung durch: Wenn derselbe Schlüssel sowohl in obj1 als auch in obj2 vorhanden ist, wird der Wert in obj2 beibehalten, der Wert in obj1 wird gelöscht. Wenn z.B. das Beispiel der Frage var obj2 = { animal: 'dog', food: 'bone' }; wäre die Verschmelzung { food: 'bone', car: 'ford', animal: 'dog' } . Wenn Sie mit "verschachtelten Daten" arbeiten und eine "tiefe Zusammenführung" wünschen, suchen Sie nach Antworten, die "tiefe Zusammenführung" oder "Rekursion" erwähnen. Wenn Sie Werte haben, die arrays verwenden Sie dann die Option "arrayMerge" von github "TehShrike/deepmerge", wie erwähnt aquí .

2voto

RobKohr Punkte 6114

Verwendung:

//Takes any number of objects and returns one merged object
var objectMerge = function(){
    var out = {};
    if(!arguments.length)
        return out;
    for(var i=0; i<arguments.length; i++) {
        for(var key in arguments[i]){
            out[key] = arguments[i][key];
        }
    }
    return out;
}

Es wurde getestet mit:

console.log(objectMerge({a:1, b:2}, {a:2, c:4}));

Das Ergebnis ist:

{ a: 2, b: 2, c: 4 }

2voto

Gossi's Erweiterung der Methode von David Coallier:

Überprüfen Sie diese beiden Zeilen:

from = arguments[i];
Object.getOwnPropertyNames(from).forEach(function (name) {

Man muss "von" gegen ein Null-Objekt prüfen... Wenn man zum Beispiel ein Objekt zusammenführt, das von einem Ajax Antwort, die zuvor auf einem Server erstellt wurde, kann eine Objekteigenschaft den Wert "null" haben, und in diesem Fall erzeugt der obige Code eine Fehlermeldung:

"von" ist kein gültiges Objekt

So kann zum Beispiel die Funktion "...Object.getOwnPropertyNames(from).forEach..." mit einem "if (from != null) { ... }", um diesen Fehler zu vermeiden.

2voto

Deen John Punkte 2948

flach

var obj = { name : "Jacob" , address : ["America"] }
var obj2 = { name : "Shaun" , address : ["Honk Kong"] }

var merged = Object.assign({} , obj,obj2 ); //shallow merge 
obj2.address[0] = "new city"

result.address[0] wird in "neue Stadt" geändert, d.h. das zusammengeführte Objekt wird ebenfalls geändert. Dies ist das Problem bei der oberflächlichen Zusammenführung.

tief

var obj = { name : "Jacob" , address : ["America"] }
var obj2 = { name : "Shaun" , address : ["Honk Kong"] }

var result = Object.assign({} , JSON.parse(JSON.stringify(obj)),JSON.parse(JSON.stringify(obj2)) )

obj2.address[0] = "new city"

result.address[0] wird nicht geändert

0 Stimmen

Var merged = Object.assign({} , obj,obj2 ) wird nichts zusammengeführt?

2voto

vsync Punkte 101339
function extend(o, o1, o2){
    if( !(o instanceof Object) ) o = {};

    copy(o, o1);
    if( o2 )
        copy(o, o2)

    function isObject(obj) {
        var type = Object.prototype.toString.call(obj);
        return obj === Object(obj) && type != '[object Array]' && type != '[object Function]';
    };

    function copy(a,b){
        // copy o2 to o
        for( var key in b )
            if( b.hasOwnProperty(key) ){
                if( isObject(b[key]) ){
                    if( !isObject(a[key]) )
                        a[key] = Object.assign({}, b[key]); 
                    else copy(a[key], b[key])
                }
                else
                    a[key] = b[key];
            }
    }

    return o;
};

var o1 = {a:{foo:1}, b:1},
    o2 = {a:{bar:2}, b:[1], c:()=>{}},
    newMerged = extend({}, o1, o2);

console.log( newMerged )
console.log( o1 )
console.log( o2 )

4 Stimmen

Dies kippt, wenn o2 irgendwelche Eigenschaften enthält, die nicht bereits in o1 vorhanden sind, was genau der Grund ist, warum Markus die try/catch, die Sie entfernt haben, hat. Ihr Beispiel funktioniert nur, weil alle Eigenschaften von o2 bereits in o1 vorhanden sind. Es handelt sich also nicht um eine Zusammenführung, und es ist auch nicht besser!

0 Stimmen

Nein, es scheitert nicht, ich habe gerade versucht, was Sie gesagt haben, mit Erfolg.

0 Stimmen

Man sollte beachten, dass die Funktion destruktiv ist und obj1 wie auch werden alle darin verschachtelten Objekte geändert, was vielleicht nicht das ist, was Sie wollten. Ich habe die Funktion und die Argumente umbenannt in applyProperties(target, source) mich selbst, um Klarheit zu schaffen.

2voto

bravedick Punkte 7012

Meine Art:

function mergeObjects(defaults, settings) {
    Object.keys(defaults).forEach(function(key_default) {
        if (typeof settings[key_default] == "undefined") {
            settings[key_default] = defaults[key_default];
        } else if (isObject(defaults[key_default]) && isObject(settings[key_default])) {
            mergeObjects(defaults[key_default], settings[key_default]);
        }
    });

    function isObject(object) {
        return Object.prototype.toString.call(object) === '[object Object]';
    }

    return settings;
}

:)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X