Domanda Come posso unire le proprietà di due oggetti JavaScript in modo dinamico?


Devo essere in grado di unire due (molto semplici) oggetti JavaScript in fase di esecuzione. Ad esempio mi piacerebbe:

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

obj1.merge(obj2);

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

Qualcuno ha uno script per questo o sa di un modo per farlo? Non ho bisogno di ricorsione, e non ho bisogno di unire funzioni, solo metodi su oggetti piatti.


1825


origine


risposte:


Metodo standard ECMAScript 2018

Tu useresti oggetto diffuso:

let merged = {...obj1, ...obj2};

/** There's no limit to the number of objects you can merge.
 *  Later properties overwrite earlier properties with the same name. */
const allRules = {...obj1, ...obj2, ...obj3};

Metodo standard ECMAScript 2015 (ES6)

/* For the case in question, you would do: */
Object.assign(obj1, obj2);

/** There's no limit to the number of objects you can merge.
 *  All objects get merged into the first object. 
 *  Only the object in the first argument is mutated and returned.
 *  Later properties overwrite earlier properties with the same name. */
const allRules = Object.assign({}, obj1, obj2, obj3, etc);

(vedere Riferimento JavaScript MDN)


Metodo per ES5 e precedenti

for (var attrname in obj2) { obj1[attrname] = obj2[attrname]; }

Si noti che questo aggiungerà semplicemente tutti gli attributi di obj2 a obj1 che potrebbe non essere quello che vuoi se vuoi ancora usare il non modificato obj1.

Se stai usando un framework che fa schifo su tutti i tuoi prototipi, allora devi diventare più fanatico con assegni come hasOwnProperty, ma quel codice funzionerà per il 99% dei casi.

Funzione di esempio:

/**
 * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
 * @param obj1
 * @param obj2
 * @returns obj3 a new object based on obj1 and obj2
 */
function merge_options(obj1,obj2){
    var obj3 = {};
    for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
    for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
    return obj3;
}

1885



jQuery ha anche un'utilità per questo: http://api.jquery.com/jQuery.extend/.

Tratto dalla documentazione di jQuery:

// Merge options object into settings object
var settings = { validate: false, limit: 5, name: "foo" };
var options  = { validate: true, name: "bar" };
jQuery.extend(settings, options);

// Now the content of settings object is the following:
// { validate: true, limit: 5, name: "bar" }

Il codice precedente muterà il oggetto esistente di nome settings.


Se vuoi creare un nuovo oggetto senza modificare alcun argomento, usa questo:

var defaults = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };

/* Merge defaults and options, without modifying defaults */
var settings = $.extend({}, defaults, options);

// The content of settings variable is now the following:
// {validate: true, limit: 5, name: "bar"}
// The 'defaults' and 'options' variables remained the same.

1114



Il Harmony ECMAScript 2015 (ES6) specifica Object.assign che lo farà.

Object.assign(obj1, obj2);

L'attuale supporto per il browser è migliorare, ma se stai sviluppando per i browser che non dispongono di supporto, puoi utilizzare a polyfill.


310



Ho cercato su google il codice per unire le proprietà dell'oggetto e sono finito qui. Tuttavia, poiché non c'era alcun codice per la fusione ricorsiva, l'ho scritto io stesso. (Forse jQuery estende è ricorsivo BTW?) Comunque, si spera che qualcun altro lo troverà utile pure.

(Ora il codice non usa Object.prototype :)

Codice

/*
* Recursively merge properties of two objects 
*/
function MergeRecursive(obj1, obj2) {

  for (var p in obj2) {
    try {
      // Property in destination object set; update its value.
      if ( obj2[p].constructor==Object ) {
        obj1[p] = MergeRecursive(obj1[p], obj2[p]);

      } else {
        obj1[p] = obj2[p];

      }

    } catch(e) {
      // Property in destination object not set; create it and set its value.
      obj1[p] = obj2[p];

    }
  }

  return obj1;
}

Un esempio

o1 = {  a : 1,
        b : 2,
        c : {
          ca : 1,
          cb : 2,
          cc : {
            cca : 100,
            ccb : 200 } } };

o2 = {  a : 10,
        c : {
          ca : 10,
          cb : 20, 
          cc : {
            cca : 101,
            ccb : 202 } } };

o3 = MergeRecursive(o1, o2);

Produce oggetto o3 come

o3 = {  a : 10,
        b : 2,
        c : {
          ca : 10,
          cb : 20,
          cc : { 
            cca : 101,
            ccb : 202 } } };

226



Nota che underscore.js'S extend-metodo fa questo in un one-liner:

_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}

166



Simile a jQuery extend (), hai la stessa funzione in AngularJS:

// Merge the 'options' object into the 'settings' object
var settings = {validate: false, limit: 5, name: "foo"};
var options  = {validate: true, name: "bar"};
angular.extend(settings, options);

80



Ho bisogno di unire gli oggetti oggi e questa domanda (e le risposte) mi hanno aiutato molto. Ho provato alcune risposte, ma nessuna corrisponde alle mie esigenze, quindi ho unito alcune delle risposte, ho aggiunto qualcosa di me stesso e ho creato una nuova funzione di unione. Ecco qui:

var merge = function() {
    var obj = {},
        i = 0,
        il = arguments.length,
        key;
    for (; i < il; i++) {
        for (key in arguments[i]) {
            if (arguments[i].hasOwnProperty(key)) {
                obj[key] = arguments[i][key];
            }
        }
    }
    return obj;
};

Alcuni esempi di utilizzo:

var t1 = {
    key1: 1,
    key2: "test",
    key3: [5, 2, 76, 21]
};
var t2 = {
    key1: {
        ik1: "hello",
        ik2: "world",
        ik3: 3
    }
};
var t3 = {
    key2: 3,
    key3: {
        t1: 1,
        t2: 2,
        t3: {
            a1: 1,
            a2: 3,
            a4: [21, 3, 42, "asd"]
        }
    }
};

console.log(merge(t1, t2));
console.log(merge(t1, t3));
console.log(merge(t2, t3));
console.log(merge(t1, t2, t3));
console.log(merge({}, t1, { key1: 1 }));

58