Hoe kan ik eigenschappen van twee JavaScript-objecten dynamisch samenvoegen?

Ik moet tijdens runtime twee (zeer eenvoudige) JavaScript-objecten kunnen samenvoegen. Ik wil bijvoorbeeld:

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
obj1.merge(obj2);
//obj1 now has three properties: food, car, and animal

Heeft iemand hier een script voor of weet iemand een ingebouwde manier om dit te doen? Ik heb geen recursie nodig en ik hoef geen functies samen te voegen, alleen methoden op platte objecten.


Antwoord 1, autoriteit 100%

ECMAScript 2018 standaardmethode

Je zou objectspreadgebruiken:

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

mergedis nu de vereniging van obj1en obj2. Eigenschappen in obj2overschrijven die in obj1.

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

Hier is ook de MDN-documentatievoor deze syntaxis. Als je babel gebruikt, heb je de babel- plugin-transform-object-rest-spreadplugin om het te laten werken.

ECMAScript 2015 (ES6) standaardmethode

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

(zie MDN Javascript Reference )


methode voor ES5 en eerder

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

Merk op dat dit eenvoudig alle kenmerken van obj2toevoegen aan obj1, wat mogelijk niet is wat u wilt als u de niet-gemoduceerde obj1.

Als u een raamwerk gebruikt dat in uw prototypes innen, moet u liefhebber met cheques als hasOwnProperty, maar die code zal voor 99% van de gevallen werken.

Voorbeeldfunctie:

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

2, Autoriteit 36%

jQuery heeft hier ook een hulpprogramma voor: http://api.jquery.com/jQuery.extend /.

Genomen uit de jQuery-documentatie:

// 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" }

De bovenstaande code muteert het bestaande objectmet de naam settings.


Als u een nieuw objectwilt maken zonder een van de argumenten aan te passen, gebruikt u dit:

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.

Antwoord 3, autoriteit 11%

De Harmony ECMAScript 2015 (ES6)specificeert Object.assigndie dit zal doen.

Object.assign(obj1, obj2);

De huidige browserondersteuning is wordt beter, maar als u ontwikkelt voor browsers die geen ondersteuning hebben, kunt u een polyfill.


Antwoord 4, autoriteit 8%

Ik googelde op code om objecteigenschappen samen te voegen en kwam hier terecht. Omdat er echter geen code was voor recursieve samenvoeging, heb ik deze zelf geschreven. (Misschien is jQuery extend recursief btw?) Hoe dan ook, hopelijk vindt iemand anders het ook nuttig.

(De code gebruikt nu geen 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;
}

Een voorbeeld

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

Produceert object o3 zoals

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

Antwoord 5, autoriteit 5%

Merk op dat underscore.js‘s extend-methodedoet dit in een one-liner:

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

Antwoord 6, autoriteit 2%

Vergelijkbaar met jQuery extend(), heeft u dezelfde functie 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);

Antwoord 7, autoriteit 2%

Ik moet vandaag objecten samenvoegen, en deze vraag (en antwoorden) heeft me erg geholpen. Ik heb een aantal van de antwoorden geprobeerd, maar geen van hen paste bij mijn behoeften, dus ik heb een aantal van de antwoorden gecombineerd, zelf iets toegevoegd en een nieuwe samenvoegfunctie bedacht. Hier is het:

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

Enkele voorbeelden van gebruik:

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

8, Autoriteit 2%

U kunt de Object Spread Syntaxis Om dit te bereiken. Het maakt deel uit van ES2018 en daarbuiten.

const obj1 = { food: 'pizza', car: 'ford' };
const obj2 = { animal: 'dog' };
const obj3 = { ...obj1, ...obj2 };
console.log(obj3);

9

Samenvoegende eigenschappen van n-objecten in één regel code

Een Object.assign-methode maakt deel uit van de Ecmascript 2015 (ES6) -standaard en doet precies wat u nodig hebt. (IEniet ondersteund)

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

De methode voor object.Assign () wordt gebruikt om de waarden van alle traaglijke eigen eigenschappen van een of meer bronobjecten naar een doelobject te kopiëren.

Lees meer …

De polyfillom oudere browsers te ondersteunen:

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

Antwoord 10

De gegeven oplossingen moeten worden aangepast om source.hasOwnProperty(property)te controleren in de for..in-lussen voordat ze worden toegewezen – anders kopieer je de eigenschappen van de hele prototypeketen, wat zelden gewenst is…


Antwoord 11

De volgende twee zijn waarschijnlijk een goed startpunt. lodash heeft ook een aanpassingsfunctie voor die speciale behoeften!

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


Antwoord 12

Trouwens, wat u allemaal doet is eigenschappen overschrijven, niet samenvoegen…

Zo is het gebied met JavaScript-objecten echt samengevoegd: alleen sleutels in het to-object die zelf geen objecten zijn, worden overschreven door from. Al het andere wordt echt samengevoegd. Natuurlijk kun je dit gedrag veranderen om niets te overschrijven dat bestaat, zoals alleen als to[n] is undefined, enz…:

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

Gebruik:

var merged = realMerge(obj1, obj2);

Antwoord 13

Hier is mijn steek die

  1. Ondersteunt diepe samenvoeging
  2. Muteert geen argumenten
  3. Neemt een willekeurig aantal argumenten
  4. Brengt het objectprototype niet uit
  5. Niet afhankelijk van een andere bibliotheek (jQuery, MooTools, Underscore .js, enz.)
  6. Inclusief controle op hasOwnProperty
  7. Is kort 🙂

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

Voorbeeld:

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

14

object.Assign ()

Ecmascript 2015 (ES6)

Dit is een nieuwe technologie, onderdeel van de Ecmascript 2015 (ES6) -standaard.
De specificatie van deze technologie is afgerond, maar controleer de compatibiliteitstabel voor gebruik en implementatiestatus in verschillende browsers.

De methode van het object.Assign () wordt gebruikt om de waarden van alle traaglijke eigen eigenschappen van een of meer bronobjecten naar een doelobject te kopiëren. Het zal het doelobject retourneren.

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.

15

Voor niet-te-gecompliceerde objecten kunt u JSON :

gebruiken

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_/

Let op dat in dit voorbeeld “} {” niet binnen een tekenreeks mogen optreden!


16

Er is een bibliotheek met de naam deepmergeop GitHub: dat lijkt wat meer grip te krijgen. Het is een stand-alone, beschikbaar via zowel de npmals de bower-pakketbeheerders.

Ik zou geneigd zijn dit te gebruiken of te verbeteren in plaats van code uit antwoorden te kopiëren en plakken.


Antwoord 17

De beste manier om dit te doen, is door een juiste eigenschap toe te voegen die niet op te sommen is met Object.defineProperty.

Op deze manier kunt u nog steeds de eigenschappen van uw objecten herhalen zonder de nieuw gemaakte “uitbreiding” die u zou krijgen als u de eigenschap zou maken met Object.prototype.extend.

Hopelijk helpt dit:

Object.defineProperty(Object.prototype, "uitbreiden", {
  opsombaar: vals,
  waarde: functie (van) {
    var props = Object.getOwnPropertyNames (van);
    var bestemming = dit;
    props.forEach(functie(naam) {
      if (naam in bestemming) {
        var bestemming = Object.getOwnPropertyDescriptor (van, naam);
        Object.defineProperty (bestemming, naam, bestemming);
      }
    });
    geef dit terug;
  }
});

Als je dat eenmaal werkend hebt, kun je het volgende doen:

var obj = {
  naam: 'stapel',
  afwerking: 'overloop'
}
var vervanging = {
  naam: 'voorraad'
};
obj.extend(vervanging);

Ik heb er zojuist een blogpost over geschreven: http:// onemoredigit.com/post/1527191998/extending-objects-in-node-js


Antwoord 18

Je kunt jQuery gewoon gebruiken extend

var obj1 = { val1: false, limit: 5, name: "foo" };
var obj2 = { val2: true, name: "bar" };
jQuery.extend(obj1, obj2);

Nu obj1Bevat alle waarden van obj1en obj2


19

prototype heeft dit:

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

obj1.extend(obj2)WORDT WAT JE WILT.


20

** Samenvoegen van objecten is eenvoudig met Object.assignof de spread ...operator **

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog', car: 'BMW' }
var obj3 = {a: "A"}
var mergedObj = Object.assign(obj1,obj2,obj3)
 // or using the Spread operator (...)
var mergedObj = {...obj1,...obj2,...obj3}
console.log(mergedObj);

21

WOW .. Dit is de eerste Stackoverflow-bericht die ik met meerdere pagina’s heb gezien. Excuses voor het toevoegen van een ander “antwoord”

ES5 & AMP; Eerder

Deze methode is voor ES5 & amp; Eerder – er zijn tal van andere antwoorden die ES6-adres hebben.

Ik heb geen “Deep” Object-fusie zien met behulp van de argumentsonroerend goed. Hier is mijn antwoord – Compact & AMP; Recursief , waardoor onbeperkte objectargemen worden gepasseerd:

function extend() {
    for (var o = {}, i = 0; i < arguments.length; i++) {
        // Uncomment to skip arguments that are not objects (to prevent errors)
        // 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;
}

Voorbeeld


22

Ik heb de methode van David Coallier uitgebreid:

  • voegde de mogelijkheid toe om meerdere objecten
  • samen te voegen

  • Ondersteunt diepe objecten
  • parameter overschrijven (die wordt gedetecteerd als de laatste parameter een boolean is)

Als overschrijven onwaar is, wordt geen enkele eigenschap overschreven, maar worden er nieuwe eigenschappen toegevoegd.

Gebruik:
obj.merge(samenvoegen… [, overschrijven]);

Hier is mijn code:

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

Voorbeelden en testcases:

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

My Equals-methode is hier te vinden: Objectvergelijking in JavaScript


23

in mootools , er is Object.merge () :

Object.merge(obj1, obj2);

24

in ext & nbsp; js 4 Het kan als volgt worden gedaan:

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

Zie samenvoegen (object): object .


25

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

met jQuery.extend () link

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

met behulp van _.merge () link

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

Gebruik _.extend()Link

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

Object.assign() ECMAScript 2015 (ES6) gebruikenLink

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

Uitvoer van alles

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

Antwoord 26

Gebaseerd op Markus’en antwoord van vsync, dit is een uitgebreide versie. De functie heeft een willekeurig aantal argumenten. Het kan worden gebruikt om eigenschappen in te stellen op DOM-knooppunten en maakt diepe kopieën van waarden. Het eerste argument wordt echter als referentie gegeven.

Om een DOM-knooppunt te detecteren, wordt de functie isDOMNode() gebruikt (zie Stack Overflow-vraag JavaScript isDOM — Hoe u controleert of een JavaScript-object een DOM-object is?)

Het is getest in Opera11, Firefox 6, Internet Explorer 8en Google Chrome 16.

Code

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

Enkele voorbeelden

InnerHTML en stijl van een HTML-element instellen

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

Matrices en objecten samenvoegen. Merk op dat undefined kan worden gebruikt om waarden in de linker array/het object te behouden.

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

Elk argument dat geen JavaScript-object is (inclusief null) wordt genegeerd. Behalve het eerste argument worden ook DOM-knooppunten weggegooid. Pas op dat d.w.z. strings, gemaakt als nieuwe String() in feite objecten zijn.

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

Als je twee objecten wilt samenvoegen tot een nieuw (zonder een van de twee te beïnvloeden), geef dan {} als eerste argument

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

Bewerken(door ReaperSoon):

Ook arrays samenvoegen

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

Antwoord 27

U moet defaultsDeep

van lodash gebruiken

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

Antwoord 28

Met Underscore.js, om een array van objecten samen te voegen:

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

Het resulteert in:

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

Antwoord 29

let obj1 = {a:1, b:2};
let obj2 = {c:3, d:4};
let merged = {...obj1, ...obj2};
console.log(merged);

Other episodes