Domanda

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

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 conosce un modo integrato per farlo? Non ho bisogno di ricorsione e non ho bisogno di unire funzioni, solo metodi su oggetti piatti.

È stato utile?

Soluzione

Metodo standard ECMAScript 2018

Dovresti utilizzare diffusione oggetti :

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

(vedi Riferimento MDN JavaScript )


Metodo per ES5 e precedenti

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

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

Se stai usando un framework che si diffonde su tutti i tuoi prototipi, devi diventare più elaborato con controlli come hasOwnProperty , ma quel codice funzionerà per il 99% dei casi.

Esempio di funzione:

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

Altri suggerimenti

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 sopra cambierà il oggetto esistente chiamato settings .


Se vuoi creare un nuovo oggetto senza modificare nessuno dei due argomenti, 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.

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

Object.assign(obj1, obj2);

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

Ho cercato su Google il codice per unire le proprietà degli oggetti e sono finito qui. Tuttavia, poiché non c'era alcun codice per l'unione ricorsiva, l'ho scritto da solo. (Forse jQuery extension è ricorsivo a proposito?) Comunque, si spera che anche qualcun altro lo trovi utile.

(Ora il codice non utilizza 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 l'oggetto o3 come

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

Nota che underscore.js è estende -method fa questo in una riga:

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

Simile a jQuery extension (), 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);

Oggi devo unire gli oggetti e questa domanda (e risposte) mi ha aiutato molto. Ho provato alcune delle risposte, ma nessuna di queste si adattava alle mie esigenze, quindi ho combinato alcune delle risposte, aggiunto qualcosa da me e ho trovato una nuova funzione di unione. Eccolo:

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

Puoi utilizzare proprietà di diffusione degli oggetti & # 8212; attualmente una proposta ECMAScript della terza fase .

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

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

Le soluzioni fornite devono essere modificate per controllare source.hasOwnProperty (proprietà) nei cicli for..in prima di assegnare - altrimenti, si finisce per copiare le proprietà di l'intera catena di prototipi, che raramente si desidera ...

Unisci le proprietà di N oggetti in una riga di codice

Un metodo Object.assign fa parte dello standard ECMAScript 2015 (ES6) e fa esattamente ciò di cui hai bisogno. ( IE non supportato)

var clone = Object.assign({}, obj);
  

Il metodo Object.assign () viene utilizzato per copiare i valori di tutte le proprietà proprie enumerabili da uno o più oggetti di origine in un oggetto di destinazione.

Leggi di più ...

Il polifill per supportare i browser più vecchi:

if (!Object.assign) {
  Object.defineProperty(Object, 'assign', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(target) {
      'use strict';
      if (target === undefined || target === null) {
        throw new TypeError('Cannot convert first argument to object');
      }

      var to = Object(target);
      for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        if (nextSource === undefined || nextSource === null) {
          continue;
        }
        nextSource = Object(nextSource);

        var keysArray = Object.keys(nextSource);
        for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
          var nextKey = keysArray[nextIndex];
          var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
          if (desc !== undefined && desc.enumerable) {
            to[nextKey] = nextSource[nextKey];
          }
        }
      }
      return to;
    }
  });
}

I seguenti due sono probabilmente un buon punto di partenza. lodash ha anche una funzione di personalizzazione per quelle esigenze speciali!

_.extend ( http://underscorejs.org/#extend )
_.merge ( https://lodash.com/docs#merge )

A proposito, tutto quello che stai facendo è sovrascrivere le proprietà, non unire ...

Ecco come gli oggetti JavaScript si sono davvero uniti: solo le chiavi dell'oggetto in che non sono oggetti stessi verranno sovrascritte da da . Tutto il resto sarà veramente unito . Ovviamente puoi cambiare questo comportamento per non sovrascrivere qualsiasi cosa esista solo se in [n] non è definito , ecc ...:

var realMerge = function (to, from) {

    for (n in from) {

        if (typeof to[n] != 'object') {
            to[n] = from[n];
        } else if (typeof from[n] == 'object') {
            to[n] = realMerge(to[n], from[n]);
        }
    }
    return to;
};

Utilizzo:

var merged = realMerge(obj1, obj2);

Ecco la mia pugnalata che

  1. Supporta l'unione profonda
  2. Non muta gli argomenti
  3. Accetta qualsiasi numero di argomenti
  4. Non estende il prototipo dell'oggetto
  5. Non dipende da un'altra libreria ( jQuery , MooTools , Underscore .js , ecc.)
  6. Include il controllo di hasOwnProperty
  7. È breve :)

    /*
        Recursively merge properties and return new object
        obj1 &lt;- obj2 [ &lt;- ... ]
    */
    function merge () {
        var dst = {}
            ,src
            ,p
            ,args = [].splice.call(arguments, 0)
        ;
    
        while (args.length > 0) {
            src = args.splice(0, 1)[0];
            if (toString.call(src) == '[object Object]') {
                for (p in src) {
                    if (src.hasOwnProperty(p)) {
                        if (toString.call(src[p]) == '[object Object]') {
                            dst[p] = merge(dst[p] || {}, src[p]);
                        } else {
                            dst[p] = src[p];
                        }
                    }
                }
            }
        }
    
       return dst;
    }
    

Esempio:

a = {
    "p1": "p1a",
    "p2": [
        "a",
        "b",
        "c"
    ],
    "p3": true,
    "p5": null,
    "p6": {
        "p61": "p61a",
        "p62": "p62a",
        "p63": [
            "aa",
            "bb",
            "cc"
        ],
        "p64": {
            "p641": "p641a"
        }
    }
};

b = {
    "p1": "p1b",
    "p2": [
        "d",
        "e",
        "f"
    ],
    "p3": false,
    "p4": true,
    "p6": {
        "p61": "p61b",
        "p64": {
            "p642": "p642b"
        }
    }
};

c = {
    "p1": "p1c",
    "p3": null,
    "p6": {
        "p62": "p62c",
        "p64": {
            "p643": "p641c"
        }
    }
};

d = merge(a, b, c);


/*
    d = {
        "p1": "p1c",
        "p2": [
            "d",
            "e",
            "f"
        ],
        "p3": null,
        "p5": null,
        "p6": {
            "p61": "p61b",
            "p62": "p62c",
            "p63": [
                "aa",
                "bb",
                "cc"
            ],
            "p64": {
                "p641": "p641a",
                "p642": "p642b",
                "p643": "p641c"
            }
        },
        "p4": true
    };
*/

Object.assign ()

ECMAScript 2015 (ES6)

Questa è una nuova tecnologia, parte dello standard ECMAScript 2015 (ES6). Le specifiche di questa tecnologia sono state finalizzate, ma controlla la tabella di compatibilità per lo stato di utilizzo e implementazione in vari browser.

Il metodo Object.assign () viene utilizzato per copiare i valori di tutte le proprietà proprie enumerabili da uno o più oggetti di origine in un oggetto di destinazione. Restituirà l'oggetto di destinazione.

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 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, target object itself is changed.

Per oggetti non troppo complicati puoi usare JSON :

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

objMerge = JSON.stringify(obj1) + JSON.stringify(obj2);

// {"food": "pizza","car":"ford"}{"animal":"dog","car":"chevy"}

objMerge = objMerge.replace(/\}\{/, ","); //  \_ replace with comma for valid JSON

objMerge = JSON.parse(objMerge); // { food: 'pizza', animal: 'dog', car: 'chevy'}
// Of same keys in both objects, the last object's value is retained_/

Ricordati che in questo esempio "} {" non deve essere presente all'interno di una stringa!

Il modo migliore per farlo è quello di aggiungere una proprietà corretta che non sia enumerabile usando Object.defineProperty.

In questo modo sarai ancora in grado di scorrere le proprietà dei tuoi oggetti senza avere la "nuova estensione" appena creata che otterresti se dovessi creare la proprietà con Object.prototype.extend.

Speriamo che questo aiuti:

Object.defineProperty(Object.prototype, "extend", {
    enumerable: false,
    value: function(from) {
        var props = Object.getOwnPropertyNames(from);
        var dest = this;
        props.forEach(function(name) {
            if (name in dest) {
                var destination = Object.getOwnPropertyDescriptor(from, name);
                Object.defineProperty(dest, name, destination);
            }
        });
        return this;
    }
});

Una volta che hai funzionato, puoi fare:

var obj = {
    name: 'stack',
    finish: 'overflow'
}
var replacement = {
    name: 'stock'
};

obj.extend(replacement);

Ho appena scritto un post sul blog qui: http: // onemoredigit.com/post/1527191998/extending-objects-in-node-js

Puoi semplicemente usare jQuery extend

var obj1 = { val1: false, limit: 5, name: "foo" };
var obj2 = { val2: true, name: "bar" };

jQuery.extend(obj1, obj2);

Ora obj1 contiene tutti i valori di obj1 e obj2

Esiste una libreria chiamata deepmerge su GitHub : sembra che stia ottenendo una certa trazione. È un programma autonomo, disponibile sia attraverso npm sia con i gestori di pacchetti di bower.

Sarei propenso a utilizzare o migliorare questo invece di copiare e incollare il codice dalle risposte.

Prototype ha questo:

Object.extend = function(destination,source) {
    for (var property in source)
        destination[property] = source[property];
    return destination;
}

obj1.extend (obj2) farà ciò che desideri.

Solo se qualcuno sta utilizzando Google Closure Library :

goog.require('goog.object');
var a = {'a': 1, 'b': 2};
var b = {'b': 3, 'c': 4};
goog.object.extend(a, b);
// Now object a == {'a': 1, 'b': 3, 'c': 4};

Esiste una funzione di supporto simile per l'array :

var a = [1, 2];
var b = [3, 4];
goog.array.extend(a, b); // Extends array 'a'
goog.array.concat(a, b); // Returns concatenation of array 'a' and 'b'

Ho esteso il metodo di David Coallier:

  • Aggiunta la possibilità di unire più oggetti
  • Supporta oggetti profondi
  • sovrascrive il parametro (viene rilevato se l'ultimo parametro è un valore booleano)

Se l'override è falso, nessuna proprietà viene sovrascritta ma verranno aggiunte nuove proprietà.

Utilizzo: obj.merge (unisce ... [, ignora]);

Ecco il mio codice:

Object.defineProperty(Object.prototype, "merge", {
    enumerable: false,
    value: function () {
        var override = true,
            dest = this,
            len = arguments.length,
            props, merge, i, from;

        if (typeof(arguments[arguments.length - 1]) === "boolean") {
            override = arguments[arguments.length - 1];
            len = arguments.length - 1;
        }

        for (i = 0; i < len; i++) {
            from = arguments[i];
            if (from != null) {
                Object.getOwnPropertyNames(from).forEach(function (name) {
                    var descriptor;

                    // nesting
                    if ((typeof(dest[name]) === "object" || typeof(dest[name]) === "undefined")
                            && typeof(from[name]) === "object") {

                        // ensure proper types (Array rsp Object)
                        if (typeof(dest[name]) === "undefined") {
                            dest[name] = Array.isArray(from[name]) ? [] : {};
                        }
                        if (override) {
                            if (!Array.isArray(dest[name]) && Array.isArray(from[name])) {
                                dest[name] = [];
                            }
                            else if (Array.isArray(dest[name]) && !Array.isArray(from[name])) {
                                dest[name] = {};
                            }
                        }
                        dest[name].merge(from[name], override);
                    } 

                    // flat properties
                    else if ((name in dest && override) || !(name in dest)) {
                        descriptor = Object.getOwnPropertyDescriptor(from, name);
                        if (descriptor.configurable) {
                            Object.defineProperty(dest, name, descriptor);
                        }
                    }
                });
            }
        }
        return this;
    }
});

Esempi e casi di prova:

function clone (obj) {
    return JSON.parse(JSON.stringify(obj));
}
var obj = {
    name : "trick",
    value : "value"
};

var mergeObj = {
    name : "truck",
    value2 : "value2"
};

var mergeObj2 = {
    name : "track",
    value : "mergeObj2",
    value2 : "value2-mergeObj2",
    value3 : "value3"
};

assertTrue("Standard", clone(obj).merge(mergeObj).equals({
    name : "truck",
    value : "value",
    value2 : "value2"
}));

assertTrue("Standard no Override", clone(obj).merge(mergeObj, false).equals({
    name : "trick",
    value : "value",
    value2 : "value2"
}));

assertTrue("Multiple", clone(obj).merge(mergeObj, mergeObj2).equals({
    name : "track",
    value : "mergeObj2",
    value2 : "value2-mergeObj2",
    value3 : "value3"
}));

assertTrue("Multiple no Override", clone(obj).merge(mergeObj, mergeObj2, false).equals({
    name : "trick",
    value : "value",
    value2 : "value2",
    value3 : "value3"
}));

var deep = {
    first : {
        name : "trick",
        val : "value"
    },
    second : {
        foo : "bar"
    }
};

var deepMerge = {
    first : {
        name : "track",
        anotherVal : "wohoo"
    },
    second : {
        foo : "baz",
        bar : "bam"
    },
    v : "on first layer"
};

assertTrue("Deep merges", clone(deep).merge(deepMerge).equals({
    first : {
        name : "track",
        val : "value",
        anotherVal : "wohoo"
    },
    second : {
        foo : "baz",
        bar : "bam"
    },
    v : "on first layer"
}));

assertTrue("Deep merges no override", clone(deep).merge(deepMerge, false).equals({
    first : {
        name : "trick",
        val : "value",
        anotherVal : "wohoo"
    },
    second : {
        foo : "bar",
        bar : "bam"
    },
    v : "on first layer"
}));

var obj1 = {a: 1, b: "hello"};
obj1.merge({c: 3});
assertTrue(obj1.equals({a: 1, b: "hello", c: 3}));

obj1.merge({a: 2, b: "mom", d: "new property"}, false);
assertTrue(obj1.equals({a: 1, b: "hello", c: 3, d: "new property"}));

var obj2 = {};
obj2.merge({a: 1}, {b: 2}, {a: 3});
assertTrue(obj2.equals({a: 3, b: 2}));

var a = [];
var b = [1, [2, 3], 4];
a.merge(b);
assertEquals(1, a[0]);
assertEquals([2, 3], a[1]);
assertEquals(4, a[2]);


var o1 = {};
var o2 = {a: 1, b: {c: 2}};
var o3 = {d: 3};
o1.merge(o2, o3);
assertTrue(o1.equals({a: 1, b: {c: 2}, d: 3}));
o1.b.c = 99;
assertTrue(o2.equals({a: 1, b: {c: 2}}));

// checking types with arrays and objects
var bo;
a = [];
bo = [1, {0:2, 1:3}, 4];
b = [1, [2, 3], 4];

a.merge(b);
assertTrue("Array stays Array?", Array.isArray(a[1]));

a = [];
a.merge(bo);
assertTrue("Object stays Object?", !Array.isArray(a[1]));

a = [];
a.merge(b);
a.merge(bo);
assertTrue("Object overrides Array", !Array.isArray(a[1]));

a = [];
a.merge(b);
a.merge(bo, false);
assertTrue("Object does not override Array", Array.isArray(a[1]));

a = [];
a.merge(bo);
a.merge(b);
assertTrue("Array overrides Object", Array.isArray(a[1]));

a = [];
a.merge(bo);
a.merge(b, false);
assertTrue("Array does not override Object", !Array.isArray(a[1]));

Il mio metodo uguale è disponibile qui: Confronto di oggetti in JavaScript

In MooTools , c'è Object.merge () :

Object.merge(obj1, obj2);

L'unione di oggetti è semplice.

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog', car: 'BMW' }
var obj3 = {a: "A"}


var mergedObj = Object.assign(obj1,obj2,obj3)

console.log(mergedObj);

Gli oggetti vengono uniti da destra a sinistra, questo significa che gli oggetti con proprietà identiche a quelli alla loro destra verranno sostituiti.

In questo esempio obj2.car sovrascrive obj1.car

In Ext & nbsp; JS 4 può essere fatto come segue:

var mergedObject = Ext.Object.merge(object1, object2)

// Or shorter:
var mergedObject2 = Ext.merge(object1, object2)

Vedi unisci (oggetto): oggetto .

Basato su Markus ' e vsync 'answer , questa è una versione espansa. La funzione accetta qualsiasi numero di argomenti. Può essere utilizzato per impostare le proprietà sui DOM e creare copie profonde dei valori. Tuttavia, il primo argomento è dato per riferimento.

Per rilevare un nodo DOM, viene utilizzata la funzione isDOMNode () (vedi Stack & nbsp; Domanda di overflow JavaScript isDOM & # 8212 ; Come si controlla se un oggetto JavaScript è un oggetto DOM? )

È stato testato in Opera 11, Firefox 6, Internet & nbsp; Explorer & nbsp; 8 e Google Chrome 16.

Codice

function mergeRecursive() {

  // _mergeRecursive does the actual job with two arguments.
  var _mergeRecursive = function (dst, src) {
    if (isDOMNode(src) || typeof src !== 'object' || src === null) {
      return dst;
    }

    for (var p in src) {
      if (!src.hasOwnProperty(p))
        continue;
      if (src[p] === undefined)
        continue;
      if ( typeof src[p] !== 'object' || src[p] === null) {
        dst[p] = src[p];
      } else if (typeof dst[p]!=='object' || dst[p] === null) {
        dst[p] = _mergeRecursive(src[p].constructor===Array ? [] : {}, src[p]);
      } else {
        _mergeRecursive(dst[p], src[p]);
      }
    }
    return dst;
  }

  // Loop through arguments and merge them into the first argument.
  var out = arguments[0];
  if (typeof out !== 'object' || out === null)
    return out;
  for (var i = 1, il = arguments.length; i < il; i++) {
    _mergeRecursive(out, arguments[i]);
  }
  return out;
}

Alcuni esempi

Imposta innerHTML e lo stile di un elemento HTML

mergeRecursive(
  document.getElementById('mydiv'),
  {style: {border: '5px solid green', color: 'red'}},
  {innerHTML: 'Hello world!'});

Unisci matrici e oggetti. Si noti che undefined può essere utilizzato per conservare i valori nell'array / oggetto di sinistra.

o = mergeRecursive({a:'a'}, [1,2,3], [undefined, null, [30,31]], {a:undefined, b:'b'});
// o = {0:1, 1:null, 2:[30,31], a:'a', b:'b'}

Qualsiasi argomento che non sia un oggetto JavaScript (incluso null) verrà ignorato. Ad eccezione del primo argomento, anche i nodi DOM vengono scartati. Fai attenzione che le stringhe, create come nuove String () sono in realtà oggetti.

o = mergeRecursive({a:'a'}, 1, true, null, undefined, [1,2,3], 'bc', new String('de'));
// o = {0:'d', 1:'e', 2:3, a:'a'}

Se si desidera unire due oggetti in un nuovo (senza influire su nessuno dei due) fornire {} come primo argomento

var a={}, b={b:'abc'}, c={c:'cde'}, o;
o = mergeRecursive(a, b, c);
// o===a is true, o===b is false, o===c is false

Modifica (di ReaperSoon):

Per unire anche le matrici

function mergeRecursive(obj1, obj2) {
  if (Array.isArray(obj2)) { return obj1.concat(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 if (Array.isArray(obj2[p])) {
        obj1[p] = obj1[p].concat(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;
}

Wow .. questo è il primo post StackOverflow che ho visto con più pagine. Ci scusiamo per l'aggiunta di un'altra "risposta"

Questo metodo è per ES5 & amp; Prima - ci sono molte altre risposte rivolte a ES6.

Non ho visto alcun oggetto " deep " che utilizza l'unione argomenti . Ecco la mia risposta - compatto & amp; ricorsivo , consentendo il passaggio di argomenti oggetto illimitati:

function extend() {
    for (var o = {}, i = 0; i < arguments.length; i++) {
        // if (arguments[i].constructor !== Object) continue;
        for (var k in arguments[i]) {
            if (arguments[i].hasOwnProperty(k)) {
                o[k] = arguments[i][k].constructor === Object ? extend(o[k] || {}, arguments[i][k]) : arguments[i][k];
            }
        }
    }
    return o;
}

La parte commentata è facoltativa .. salterà semplicemente gli argomenti passati che non sono oggetti (impedendo errori).

Esempio:

extend({
    api: 1,
    params: {
        query: 'hello'
    }
}, {
    params: {
        query: 'there'
    }
});

// outputs {api: 1, params: {query: 'there'}}
  

Questa risposta non è altro che una goccia nell'oceano ...

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

// result
result: {food: "pizza", car: "ford", animal: "dog"}

Uso di jQuery.extend () - Link

// Merge obj1 & obj2 to result
var result1 = $.extend( {}, obj1, obj2 );

Uso di _.merge () - Link

// Merge obj1 & obj2 to result
var result2 = _.merge( {}, obj1, obj2 );

Uso di _.extend () - Link

// Merge obj1 & obj2 to result
var result3 = _.extend( {}, obj1, obj2 );

Utilizzo di Object.assign () ECMAScript 2015 (ES6) - Link

// Merge obj1 & obj2 to result
var result4 = Object.assign( {}, obj1, obj2 );

Output di tutto

obj1: { animal: 'dog' }
obj2: { food: 'pizza', car: 'ford' }
result1: {food: "pizza", car: "ford", animal: "dog"}
result2: {food: "pizza", car: "ford", animal: "dog"}
result3: {food: "pizza", car: "ford", animal: "dog"}
result4: {food: "pizza", car: "ford", animal: "dog"}

Dovresti usare defaultsDeep

di lodash
_.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } });
// → { 'user': { 'name': 'barney', 'age': 36 } }

Con Underscore.js , per unire una matrice di oggetti fai:

var arrayOfObjects = [ {a:1}, {b:2, c:3}, {d:4} ];
_(arrayOfObjects).reduce(function(memo, o) { return _(memo).extend(o); });

Si traduce in:

Object {a: 1, b: 2, c: 3, d: 4}

Vale la pena ricordare che la versione della collezione 140byt.es sta risolvendo il compito in uno spazio minimo ed è vale la pena provare a questo scopo:

Codice:

function m(a,b,c){for(c in b)b.hasOwnProperty(c)&&((typeof a[c])[0]=='o'?m(a[c],b[c]):a[c]=b[c])}

Utilizzo per il tuo scopo:

m(obj1,obj2);

Ecco il Gist originale .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top