Question Comment puis-je fusionner dynamiquement les propriétés de deux objets JavaScript?


Je dois être capable de fusionner deux objets JavaScript (très simples) au moment de l'exécution. Par exemple, j'aimerais:

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

obj1.merge(obj2);

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

Quelqu'un at-il un script pour cela ou savoir d'une façon intégrée de le faire? Je n'ai pas besoin de récursion, et je n'ai pas besoin de fusionner des fonctions, seulement des méthodes sur des objets plats.


1826


origine


Réponses:


ECMAScript 2018 Méthode standard

Vous utiliseriez propagation d'objet:

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};

ECMAScript 2015 (ES6) Méthode standard

/* 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);

(voir Référence JavaScript MDN)


Méthode pour ES5 et antérieure

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

Notez que cela ajoutera simplement tous les attributs de obj2 à obj1 qui pourrait ne pas être ce que vous voulez si vous voulez toujours utiliser le non modifié obj1.

Si vous utilisez un cadre qui craps partout vos prototypes, alors vous devez obtenir plus chic avec des contrôles comme hasOwnProperty, mais ce code fonctionnera dans 99% des cas.

Exemple de fonction:

/**
 * 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;
}

1886



jQuery a également un utilitaire pour cela: http://api.jquery.com/jQuery.extend/.

Tiré de la documentation de 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" }

Le code ci-dessus va muter le objet existant nommé settings.


Si vous voulez créer un nouvel objet sans modifier aucun des arguments, utilisez ceci:

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



le Harmony ECMAScript 2015 (ES6) spécifie Object.assign qui va le faire.

Object.assign(obj1, obj2);

Le support actuel du navigateur est aller mieux, mais si vous développez pour les navigateurs qui ne disposent pas de support, vous pouvez utiliser un polyfill.


310



Je ai googlé pour le code pour fusionner les propriétés de l'objet et fini ici. Cependant puisqu'il n'y avait aucun code pour la fusion récursive je l'ai écrit moi-même. (Peut-être que jQuery extend est récursif BTW?) Quoi qu'il en soit, j'espère que quelqu'un d'autre le trouvera aussi utile.

(Maintenant, le code n'utilise pas Object.prototype :)

Code

/*
* 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 exemple

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);

Produit l'objet o3 comme

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

226



Notez que underscore.jsde extend-méthode est-ce que dans un one-liner:

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

166



Similaire à jQuery extend (), vous avez la même fonction dans 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



J'ai besoin de fusionner des objets aujourd'hui, et cette question (et réponses) m'a beaucoup aidé. J'ai essayé quelques-unes des réponses, mais aucune d'entre elles ne correspondait à mes besoins. J'ai donc combiné quelques réponses, ajouté quelque chose moi-même et créé une nouvelle fonction de fusion. C'est ici:

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;
};

Quelques exemples d'utilisations:

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



Vous pouvez utiliser propriétés de propagation d'objet- actuellement une proposition ECMAScript de niveau 3.

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

const obj3 = { ...obj1, ...obj2 };
console.log(obj3);


43