मैं दो जावास्क्रिप्ट वस्तुओं के गुणों को गतिशील रूप से कैसे मिला सकता हूं?


2516

मुझे रनटाइम पर दो (बहुत सरल) जावास्क्रिप्ट वस्तुओं को मर्ज करने में सक्षम होने की आवश्यकता है। उदाहरण के लिए:

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

obj1.merge(obj2);

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

क्या किसी के पास इसके लिए एक स्क्रिप्ट है या ऐसा करने के लिए एक अंतर्निहित तरीके से पता है? मुझे पुनरावृत्ति की आवश्यकता नहीं है, और मुझे कार्यों को मर्ज करने की आवश्यकता नहीं है, सिर्फ फ्लैट वस्तुओं पर तरीके।


एक समान प्रश्न पर इसका जवाब ध्यान देने योग्य है , जो दिखाता है कि "एक स्तर नीचे" कैसे मर्ज किया जाए। यही है, यह डुप्लिकेट कुंजियों के मानों को विलय करता है (दूसरे मूल्य के साथ पहले मूल्य को अधिलेखित करने के बजाय), लेकिन इससे आगे पुनरावृत्ति नहीं करता है। IMHO, उस कार्य के लिए इसका अच्छा साफ कोड।
टूलमेकरसैट

BTW, शीर्ष कुछ उत्तर "उथले" मर्ज करते हैं: यदि एक ही कुंजी obj1 और obj2 दोनों में मौजूद है, तो obj2 में मान रखा जाता है, obj1 में मान गिरा दिया जाता है। उदाहरण के लिए यदि प्रश्न का उदाहरण var obj2 = { animal: 'dog', food: 'bone' };होता, तो मर्ज होता { food: 'bone', car: 'ford', animal: 'dog' }। यदि आप "नेस्टेड डेटा" के साथ काम कर रहे हैं, और "डीप मर्ज" चाहते हैं, तो ऐसे उत्तर खोजें जो "डीप मर्ज" या "रिकर्सन" का उल्लेख करें। यदि आपके पास मान हैं arrays, तो "सरणी" विकल्प का उपयोग करें "तेहश्रीक / डीपमरेज", जैसा कि यहां बताया गया है
टूलमेकरसैट

कृपया नीचे दिए गए लिंक का अनुसरण करें stackoverflow.com/questions/171251/…
ईएस

जवाबों:


2903

ECMAScript 2018 मानक विधि

आप ऑब्जेक्ट स्प्रेड का उपयोग करेंगे :

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

mergedअब का मिलन है obj1और obj2। में गुण obj2उन लोगों को अधिलेखित कर देंगे 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};

इस सिंटैक्स के लिए यहाँ MDN प्रलेखन भी है । यदि आप babel का उपयोग कर रहे हैं, तो आपको इसे काम करने के लिए babel- प्लगइन-ट्रांसफ़ॉर्म-ऑब्जेक्ट-रेस्ट-स्प्रेड प्लगइन की आवश्यकता होगी।

ईसीएमएस्क्रिप्ट 2015 (ईएस 6) मानक विधि

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

( एमडीएन जावास्क्रिप्ट संदर्भ देखें )


ES5 और इससे पहले के लिए विधि

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

ध्यान दें कि यह बस की सभी विशेषताओं जोड़ देगा obj2करने के लिए obj1जो आप अभी भी असंशोधित उपयोग करना चाहते हैं नहीं हो सकता है कि आप क्या चाहते obj1

यदि आप एक ऐसे फ्रेमवर्क का उपयोग कर रहे हैं जो आपके सभी प्रोटोटाइप पर तरस खा रहा है तो आपको चेक के साथ कट्टरता प्राप्त करनी hasOwnPropertyहोगी, लेकिन यह कोड 99% मामलों में काम करेगा।

उदाहरण समारोह:

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

90
यह काम नहीं करता है यदि ऑब्जेक्ट में समान नाम विशेषताएँ हैं, और आप विशेषताओं को मर्ज करना भी चाहेंगे।
शी जे

69
यह केवल एक उथली प्रतिलिपि / मर्ज करता है। बहुत सारे तत्वों को समेटने की क्षमता रखता है।
जे टेलर टेलर

45
+1 यह स्वीकार करने के लिए कि कुछ ख़राब आत्माएँ अपने प्रोटोटाइप में
चौखट

4
यह मेरे लिए काम नहीं करता है, "इसलिए यह नई संपत्तियों की नकल या परिभाषित करने के लिए गुण बनाम असाइन करता है। इससे नई संपत्तियों को एक प्रोटोटाइप में विलय करने के लिए अनुपयुक्त हो सकता है यदि मर्ज स्रोतों में गेटर्स होते हैं।" ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… )। मुझे इस्तेमाल करना था var merged = {...obj1, ...obj2}
मोर्गेलर

2
@ ज़ीव{...obj1, ...{animal: 'dog'}}
बैकस्लैश

1190

jQuery के पास इसके लिए एक उपयोगिता भी है: http://api.jquery.com/jQuery.extend/

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

उपरोक्त कोड नाम की मौजूदा वस्तु को बदल देगा settings


यदि आप किसी भी तर्क को संशोधित किए बिना एक नई वस्तु बनाना चाहते हैं , तो इसका उपयोग करें:

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.

166
सावधान: चर "सेटिंग्स" को संशोधित किया जाएगा, यद्यपि। jQuery एक नया उदाहरण वापस नहीं करता है। इसका कारण (और नामकरण के लिए) यह है कि .extend () वस्तुओं का विस्तार करने के लिए विकसित किया गया था, न कि सामान को एक साथ मिलाने के लिए। यदि आप एक नई वस्तु चाहते हैं (जैसे सेटिंग डिफॉल्ट्स जिसे आप स्पर्श नहीं करना चाहते हैं), तो आप हमेशा jQuery.extend ({}, सेटिंग्स, विकल्प) कर सकते हैं;
वेबमैट

1
सही पर! बहुत बहुत धन्यवाद। जैसा कि पिछली टिप्पणी में कहा गया है कि इसका नाम खराब है। मैंने jQuery डॉक्स को वापस और चौथे में खोजा और इसमें नहीं चला।
माइक स्टारव

28
ध्यान रखें, jQuery.extend में एक गहरी (बूलियन) सेटिंग भी है। jQuery.extend(true,settings,override), जो महत्वपूर्ण है अगर सेटिंग्स में एक संपत्ति एक वस्तु रखती है और ओवरराइड केवल उस वस्तु का हिस्सा है। बेजोड़ गुणों को हटाने के बजाय, गहरी सेटिंग केवल वही अपडेट करेगी जहां यह मौजूद है। डिफॉल्ट गलत है।
217 बजे vol7ron

19
Geeikers, वे वास्तव में यह नामकरण एक अच्छा काम किया था। यदि आप एक जावास्क्रिप्ट वस्तु का विस्तार करने के लिए खोज करते हैं, तो यह सही है! यदि आप फ़्यूज़ या एक साथ जावास्क्रिप्ट वस्तुओं को सिलाई करने की कोशिश कर रहे हैं तो आप उस पर नहीं मार सकते।
डेरेक ग्रीर

2
लोगों को पुस्तकालय पद्धति का उपयोग करने पर विचार करने के लिए मत कहो जब वेनिला जेएस की कुछ पंक्तियां वही करेंगी जो वे चाहते हैं। JQuery से पहले एक समय था!
CrazyMerlin

346

सद्भाव ECMAScript 2015 (ES6) निर्दिष्ट करता है Object.assignजो यह कर देगा।

Object.assign(obj1, obj2);

वर्तमान ब्राउज़र समर्थन बेहतर हो रहा है , लेकिन यदि आप उन ब्राउज़रों के लिए विकसित कर रहे हैं जिनके पास समर्थन नहीं है, तो आप पॉलीफ़िल का उपयोग कर सकते हैं ।


35
ध्यान दें कि यह केवल एक उथला मर्ज है
जोकिम लूस

मुझे लगता है कि इस बीच Object.assignसुंदर सभ्य कवरेज है: kangax.github.io/compat-table/es6/…
LazerBass

13
यह अब सही उत्तर होना चाहिए। लोग आजकल अपने कोड को दुर्लभ ब्राउज़र (IE11) के साथ संगत होने के लिए संकलित करते हैं जो इस तरह की चीज का समर्थन नहीं करता है। साइड नोट: यदि आप obj1 को obj2 जोड़ने के लिए नहीं करना चाहते हैं, तो आप एक नई वस्तु का उपयोग कर लौट सकते हैंObject.assign({}, obj1, obj2)
Duvrai

6
@ डुवार्ई की रिपोर्ट्स के अनुसार, जुलाई 2016 तक बाजार के शेयर के लगभग 18% हिस्से पर IE11 निश्चित रूप से दुर्लभ नहीं है
नैनोवेयर छिपकली

3
@ कर्मी ओपी विशेष रूप से बताते हैं कि पुनरावृत्ति अनावश्यक है। इसलिए, जबकि यह जानना उपयोगी है कि यह समाधान उथले मर्ज करता है, यह उत्तर पर्याप्त है। JoachimLou की टिप्पणी को अच्छी तरह से योग्य उत्थान मिले हैं और जरूरत पड़ने पर अतिरिक्त जानकारी प्रदान करते हैं। मुझे लगता है कि गहरे और उथले विलय और समान विषयों के बीच का अंतर इस चर्चा के दायरे से परे है और अन्य एसओ प्रश्नों के लिए बेहतर है।
नैनोवेयर

264

मैं कोड के लिए googled वस्तु गुण विलय और यहाँ समाप्त हो गया। हालाँकि, पुनरावर्ती विलय के लिए कोई कोड नहीं था, मैंने इसे स्वयं लिखा था। (शायद jQuery का विस्तार पुनरावर्ती BTW है?) किसी भी तरह, उम्मीद है कि कोई और इसे उपयोगी भी पाएगा।

(अब कोड का उपयोग नहीं करता है Object.prototype:)

कोड

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

एक उदाहरण

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

ऑब्जेक्ट ओ ३ म् का निर्माण करता है

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

11
अच्छा लगा, लेकिन मैं पहले वस्तुओं की गहरी पड़ताल करूंगा। इस तरह ओ 1 को भी संशोधित किया जाएगा, क्योंकि वस्तुओं को संदर्भ द्वारा पारित किया जाता है।
स्केरिट

1
यही मैं ढूंढ रहा था। जाँच करने के लिए सुनिश्चित करें कि obj2.hasOwnProperty (p) इससे पहले कि आप कोशिश पकड़ने के बयान पर जाएं। अन्यथा, आप कुछ अन्य बकवास के साथ समाप्त हो सकते हैं जो प्रोटोटाइप श्रृंखला में उच्च से विलय हो जाते हैं।
एडम

3
धन्यवाद मार्कस। ध्यान दें कि ओ 1 को भी मर्जेसुरेसिव द्वारा संशोधित किया गया है, इसलिए अंत में ओ 1 और ओ 3 समान हैं। यदि आप कुछ भी वापस नहीं करते हैं तो यह अधिक सहज हो सकता है, इसलिए उपयोगकर्ता जानता है कि वे जो आपूर्ति कर रहे हैं (ओ 1) संशोधित हो जाता है और परिणाम बन जाता है। इसके अलावा, आपके उदाहरण में, यह ओ 2 में कुछ जोड़ने के लायक हो सकता है जो मूल रूप से ओ 1 में नहीं है, यह दिखाने के लिए कि ओ 2 गुण ओ 1 में डाला जाता है (नीचे दिए गए वैकल्पिक कोड को किसी और ने आपके उदाहरण की नकल करते हुए प्रस्तुत किया है, लेकिन जब ओ 2 में गुण नहीं होते हैं तो उनका टूट जाता है ओ 1 में - लेकिन आपका इस संबंध में काम करता है)।
पैनकेक

7
यह एक अच्छा जवाब है, लेकिन एक युगल ने कहा: 1) कोई भी तर्क अपवादों पर आधारित नहीं होना चाहिए; इस स्थिति में, किसी भी अपवाद को अप्रत्याशित परिणामों के साथ पकड़ा जाएगा। 2) मैं कुछ भी नहीं लौटने के बारे में @ पैनकेक की टिप्पणी से सहमत हूं, क्योंकि मूल वस्तु संशोधित है। यहाँ अपवाद तर्क के बिना एक jsField उदाहरण है: jsfiddle.net/jlowery2663/z8at6knn/4 - जेफ लोरी
जेफ लोवी

3
इसके अलावा, obj2 [p] .constructor == ऐरे की आवश्यकता किसी भी मामले में जहाँ वस्तुओं की एक सरणी होती है।
संगीतकार

175

ध्यान दें कि underscore.js's extend-method एक लाइनर में ऐसा करता है:

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

36
यह उदाहरण ठीक है जैसा कि आप अनाम वस्तुओं के साथ काम कर रहे हैं, लेकिन अगर ऐसा नहीं है, तो म्यूटेशन के बारे में jQuery उत्तर चेतावनी में webmat की टिप्पणी यहां लागू होती है, क्योंकि अंडरस्कोर भी गंतव्य ऑब्जेक्ट को म्यूट करता है । JQuery के उत्तर की तरह, इस उत्परिवर्तन से मुक्त करने के लिए बस एक खाली वस्तु में विलय हो जाता है:_({}).extend(obj1, obj2);
अबे वोल्कर

8
वहाँ एक और है कि आप क्या हासिल करने की कोशिश कर रहे हैं के आधार पर प्रासंगिकता हो सकती है: _.defaults(object, *defaults)"चूक वस्तुओं से मूल्यों के साथ ऑब्जेक्ट में अशक्त और अपरिभाषित गुणों को भरें, और ऑब्जेक्ट वापस करें।"
शंकु

कई लोगों ने डेस्टिनेशन ऑब्जेक्ट को म्यूट करने के बारे में टिप्पणी की है, लेकिन एक नया तरीका बनाने के बजाय, एक सामान्य पैटर्न (उदाहरण के लिए dojo) में dojo.mixin (dojo.clone (myobj), {newprotytys]: को जोड़ना है। to myobj "})
कॉलिन डी

7
अंडरस्कोर वस्तुओं की एक मनमानी संख्या ले सकता है, इसलिए आप ऐसा करके मूल वस्तु के उत्परिवर्तन से बच सकते हैं var mergedObj = _.extend({}, obj1, obj2)
लोबाती

84

JQuery विस्तार के समान (), आपके पास 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);

1
@naXa मुझे लगता है कि यह एक विकल्प होगा यदि आप इस fn के लिए केवल एक लिबास नहीं जोड़ना चाहते हैं।
जुआनम्फ

67

मुझे आज वस्तुओं को मर्ज करने की आवश्यकता है, और इस प्रश्न (और उत्तर) ने मुझे बहुत मदद की। मैंने कुछ उत्तरों की कोशिश की, लेकिन उनमें से कोई भी मेरी आवश्यकताओं के अनुरूप नहीं था, इसलिए मैंने कुछ उत्तरों को संयोजित किया, कुछ को स्वयं जोड़ा और एक नए मर्ज फ़ंक्शन के साथ आया। यह रहा:

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

कुछ उदाहरणों का उपयोग:

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

3
अच्छा उत्तर लेकिन मुझे लगता है कि यदि कोई संपत्ति पहले और दूसरे में मौजूद है और आप पहले और दूसरे में विलय करके एक नई वस्तु बनाने की कोशिश कर रहे हैं तो पहली वस्तु में मौजूद अनोखे खो जाएंगे
स्ट्राइकर्स

2
लेकिन क्या यह अपेक्षित व्यवहार नहीं है? इस फ़ंक्शन का उद्देश्य तर्क क्रम में मूल्यों को ओवरराइड करता है। अगला एक वर्तमान को ओवरराइड करेगा। आप अद्वितीय मूल्यों को कैसे संरक्षित कर सकते हैं? मेरे उदाहरण से, आप क्या उम्मीद करते हैं merge({}, t1, { key1: 1 })?
एमर इर्कन

मेरी उम्मीद केवल गैर-ऑब्जेक्ट-टाइप किए गए मानों को मर्ज करने की है।
AGamePlayer

यदि अपेक्षित परिणाम निम्नानुसार है तो विफल रहता है: gist.github.com/ceremcem/a54f90923c6e6ec42c7daf24cf2768bd
ceremcem

इसने मेरे नोड.जेएस प्रोजेक्ट के लिए मेरे लिए सख्त मोड में काम किया। अब तक, यह इस पोस्ट पर सबसे अच्छा जवाब है।
क्लेविस

48

आप ऑब्जेक्ट स्प्रेड प्रॉपर्टीज़ का उपयोग कर सकते हैं- वर्तमान में एक चरण 3 ECMAScript प्रस्ताव।

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

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


ब्राउज़र का समर्थन?
Alph.Dev

1
@ Alph.Dev आप caniuse.com जानते हैं?
कंसेक्सो

मुझे नोड में काम करने के लिए 3 डॉट सिंटैक्स नहीं मिल सकता है। नोड इसकी शिकायत करता है।
क्लेविस

41

दिए गए समाधानों को असाइन करने से पहले छोरों source.hasOwnProperty(property)में जांच करने के लिए संशोधित किया जाना चाहिए for..in- अन्यथा, आप पूरे प्रोटोटाइप श्रृंखला के गुणों की नकल करते हैं, जो शायद ही कभी वांछित है ...


40

कोड की एक पंक्ति में एन ऑब्जेक्ट्स के गुण मर्ज करें

एक Object.assignविधि ECMAScript 2015 (ES6) मानक का हिस्सा है और ठीक वही है जो आपको चाहिए। ( IEसमर्थित नहीं)

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

Object.assign () विधि का उपयोग एक या एक से अधिक स्रोत ऑब्जेक्ट से लक्ष्य सामग्री के सभी गणना करने योग्य गुणों के मूल्यों को कॉपी करने के लिए किया जाता है।

अधिक पढ़ें...

Polyfill पुराने ब्राउज़र का समर्थन करने के:

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

पुराने ब्राउज़र में 'सख्त का उपयोग करें' या ऐसा क्यों है। ब्राउज़र जो ऑब्जेक्ट का समर्थन करते हैं [डिफाइनप्रोपर्टी; चांबियाँ; getOwnPropertyDescriptor; आदि], बिल्कुल पुराने नहीं हैं। वे gen.5 यूएएस के पहले के संस्करण हैं।
बेकिम बकाज

स्पष्ट करने के लिए धन्यवाद कि Objects.assignएक विलय की गई वस्तु लौटाती है जो अन्य उत्तर नहीं देती है। यह अधिक कार्यात्मक प्रोग्रामिंग शैली है।
श्रीधर सरनोबत

36

निम्नलिखित दो शायद एक अच्छा प्रारंभिक बिंदु हैं। लॉश में उन विशेष आवश्यकताओं के लिए एक कस्टमाइज़र फ़ंक्शन भी है!

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


4
कृपया ध्यान दें कि उपरोक्त विधियाँ मूल वस्तु को बदल देती हैं।
Wtower

लॉकेट विधि ने मेरे लिए काम किया क्योंकि मैं दो वस्तुओं का विलय करना चाहता था और गुणों को अधिक से अधिक घोंसला बनाए रखना चाहता था, फिर एक या दो स्तरों को गहरा (केवल उन्हें बदलने / मिटा देने के बजाय)।
सैमब्रिक

सच्चा @Wtower बस इस वजह से एक बग था। यह सुनिश्चित करें कि यह हमेशा _.merge ({}, ...
मार्टिन क्रेमर

29

वैसे, आप जो कर रहे हैं, वह ओवरराइटिंग प्रॉपर्टीज है, मर्जिंग नहीं ...

यह इस तरह से है कि जावास्क्रिप्ट ऑब्जेक्ट क्षेत्र वास्तव में विलय कर दिया गया है: toऑब्जेक्ट में केवल कुंजियाँ जो स्वयं ऑब्जेक्ट नहीं हैं, उनके द्वारा ओवरराइट किया जाएगा from। बाकी सब कुछ वास्तव में विलय हो जाएगा । निश्चित रूप से आप इस व्यवहार को बदल सकते हैं, किसी भी चीज़ को अधिलेखित नहीं करने के लिए जो कि केवल यदि मौजूद है to[n] is undefined, आदि ...:

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

उपयोग:

var merged = realMerge(obj1, obj2);

3
मेरी बहुत मदद की, अंडरस्कोर js का विस्तार वास्तव में अधिलेखित करने के बजाय, विलय के बजाय हुआ
डेविड कॉम्प्स

1
वर्थ नोटिंग टाइपोफ़ सरणी और टाइपऑफ़ नल 'ऑब्जेक्ट' को लौटाएगा और इसे तोड़ देगा।
सालकर

@ u01jmg3 यहां मेरा उत्तर देखें: stackoverflow.com/questions/27936772/… - isObject फ़ंक्शन
सालकर

यह तब टूटता है जब आप उपयोग करते हैं। नोड्स प्रोजेक्ट्स के लिए सख्त मोड में है
क्लेविस

28

यहाँ मेरा छुरा है जो

  1. गहरे मर्ज का समर्थन करता है
  2. तर्कों को म्यूट नहीं करता है
  3. कोई भी तर्क देता है
  4. ऑब्जेक्ट प्रोटोटाइप का विस्तार नहीं करता है
  5. किसी अन्य लाइब्रेरी ( jQuery , MooTools , Underscore.js , आदि) पर निर्भर नहीं करता है
  6. HasOwnProperty के लिए जाँच शामिल है
  7. छोटा है :)

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

उदाहरण:

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

इस पृष्ठ से मेरे द्वारा परीक्षण किए गए अन्य लोगों की तुलना में, यह फ़ंक्शन वास्तव में पुनरावर्ती है (एक गहरा मर्ज करता है) और क्या jQuery.extend () वास्तव में अच्छी तरह से करता है की नकल करता है। हालाँकि, इसके लिए बेहतर होगा कि पहले ऑब्जेक्ट / तर्क को संशोधित किया जाए ताकि उपयोगकर्ता यह तय कर सके कि वे किसी खाली ऑब्जेक्ट {}को पहले पैरामीटर के रूप में पास करना चाहते हैं या फ़ंक्शन को मूल ऑब्जेक्ट को संशोधित करना है। इसलिए यदि आप इसे बदल dst = {}देते हैं तो आप dst = arguments[0]पहली वस्तु को बदल देंगे जो आप विलय की गई वस्तु में करते हैं
जसदीप खालसा

3
अब क्रोम में काम करना बंद हो गया है। मुझे लगता है कि toString.call(src) == '[object Object]'किसी वस्तु या वस्तु की जाँच के लिए ऐसे निर्माण का उपयोग करना बुरा है । typeof srcज़्यादा बेहतर है। इसके अलावा यह एर्र्स को ऑब्जेक्ट में बदल देता है (कम से कम मुझे नवीनतम क्रोम पर ऐसा व्यवहार मिला है)।
m03geek

मुझे एक लालची लूप के अंदर ऐसा करने की आवश्यकता थी, मैंने इस फ़ंक्शन को बेंचमार्क किया है। वीएस जिसे मैं अब तक _.merge (ऑब्जेक्ट, [स्रोत]) से दर्ज कर रहा था। धन्यवाद दोस्त।
अरनौद बुचोट

20

Object.assign ()

ECMAScript 2015 (ES6)

यह एक नई तकनीक है, ECMAScript 2015 (ES6) मानक का हिस्सा है। इस प्रौद्योगिकी के विनिर्देश को अंतिम रूप दिया गया है, लेकिन विभिन्न ब्राउज़रों में उपयोग और कार्यान्वयन की स्थिति के लिए संगतता तालिका की जांच करें।

Object.assign () विधि का उपयोग एक या एक से अधिक स्रोत ऑब्जेक्ट से लक्ष्य सामग्री के सभी गणना करने योग्य गुणों के मूल्यों को कॉपी करने के लिए किया जाता है। यह लक्ष्य वस्तु को लौटा देगा।

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.

19

नहीं-बहुत-जटिल वस्तुओं के लिए आप 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_/

आप का ध्यान रखें कि इस उदाहरण में "} {" एक स्ट्रिंग के भीतर नहीं होना चाहिए !


4
var so1 = JSON.stringify(obj1); var so2 = JSON.stringify(obj1); objMerge = so1.substr(0, so1.length-1)+","+so2.substr(1); console.info(objMerge);
क्लेमिस

function merge(obj1, obj2) { return JSON.parse((JSON.stringify(obj1) + JSON.stringify(obj2)) .replace(/\}\{/g, ',').replace(/,\}/g, '}').replace(/\{,/g, '{')); }
एलेक्स Ivasyuv 14

या वन-लाइनर के रूप में:objMerge = JSON.parse((JSON.stringify(obj1) + JSON.stringify(obj2)).replace(/\}\{/, ", "));
रब्बी शुकी गुर

1
@Charles, क्षमा करें, लेकिन "यह तरीका बहुत खतरनाक है" लेकिन यह भी मजेदार है - यह सबसे सुरक्षित संभव है 1 यह ऑब्जेक्ट की सामग्री को पढ़ने के भारी उठाने के लिए JSON का उपयोग करता है, दूसरी बात, यह JSON ऑब्जेक्ट का उपयोग करता है जो हर तरह से सबसे सुरक्षित है JSON संगत ऑब्जेक्ट स्ट्रिंग शाब्दिक से JSO को पुन: भेजने के लिए अनुकूलित मशीन। और IE8 के साथ भी पिछड़ा संगत है जो अपने मानक को लागू करने वाला पहला ब्राउज़र है। यह सिर्फ मुझे आश्चर्यचकित करता है "क्यों ओह, आपको ऐसी मूर्खतापूर्ण बात क्यों कहनी पड़ी और इसके साथ भाग जाना पड़ा"?
बेकिम बकाज

मेरा मानना ​​है कि ऑब्जेक्ट में फंक्शंस यहां से टूट जाएंगे क्योंकि केंटिफाई का उपयोग नहीं किया जा सकता है, लेकिन क्या हम अन्य डाउनसाइड को स्पष्ट कर सकते हैं?
येहेडिक्सन

18

GitHubdeepmerge पर एक पुस्तकालय कहा जाता है : जो कुछ कर्षण प्राप्त करता है। यह एक स्टैंडअलोन है, जो npm और bower पैकेज मैनेजर दोनों के माध्यम से उपलब्ध है ।

मैं उत्तरों से कॉपी-पेस्टिंग कोड के बजाय इस पर उपयोग या सुधार करना चाहूंगा।


17

आपके लिए ऐसा करने का सबसे अच्छा तरीका एक उचित संपत्ति जोड़ना है जो Object.defineProperty का उपयोग करके गैर-एन्यूमरेबल है।

इस तरह से आप अभी भी नए बनाए गए "विस्तार" के बिना अपनी वस्तुओं के गुणों पर पुनरावृति करने में सक्षम होंगे जो कि आप प्राप्त करेंगे यदि आप Object.prototyp.extend के साथ संपत्ति बनाना चाहते थे।

उम्मीद है कि यह मदद करता है:

Object.defineProperty (Object.prototype, "Extended", {
    असंख्य: असत्य,
    मान: फ़ंक्शन (से) {
        var प्रॉप्स = Object.getOwnPropertyNames (from);
        var dest = यह;
        props.forEach (फ़ंक्शन (नाम))
            अगर (भाग्य में नाम) {
                var गंतव्य = Object.getOwnPropertyDescriptor (से, नाम);
                Object.defineProperty (भाग्य, नाम, गंतव्य);
            }
        });
        इसे वापस करो;
    }
});

एक बार आपके पास काम करने के बाद, आप यह कर सकते हैं:

var obj = {
    नाम: 'स्टैक',
    खत्म: 'अतिप्रवाह'
}
var प्रतिस्थापन = {
    नाम: 'स्टॉक'
};

obj.extend (प्रतिस्थापन);

मैंने अभी इसके बारे में एक ब्लॉग पोस्ट लिखी है: http://onemoredigit.com/post/1527191998/extending-objects-in-node-js


एक सेकंड रुको --- कोड काम नहीं करता है! :( इसे अन्य मर्जिंग एल्गोरिदम की तुलना करने के लिए jsperf में डाला, और कोड विफल - फ़ंक्शन एक्सटेंशन मौजूद नहीं है
जेन्स रोलैंड

16

आप बस jQuery का उपयोग कर सकते हैं extend

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

jQuery.extend(obj1, obj2);

अब के obj1सभी मान शामिल हैं obj1औरobj2


2
obj1 में सभी मान शामिल होंगे, obj2 नहीं। आप पहली वस्तु का विस्तार कर रहे हैं। jQuery.extend( target [, object1 ] [, objectN ] )
खंडहर

5
यह सवाल jQuery के बारे में नहीं है। जावास्क्रिप्ट! = JQuery
जॉर्ज रेव

1
मैं जावास्क्रिप्ट के लिए Googled, लेकिन यह एक सरल तरीका है
एहसान

13

प्रोटोटाइप में यह है:

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

obj1.extend(obj2) जो चाहोगे, करोगे।


6
आपका मतलब था Object.prototyp.extend? किसी भी मामले में, Object.prototype को विस्तारित करना एक अच्छा विचार नहीं है। -1।
सॉल्यूशनयोगी

यह सोचने के लिए आओ, यह शायद होना चाहिए Object.prototypeऔर नहीं Object... अच्छा विचार या नहीं, यह वही है जो prototype.jsफ्रेमवर्क करता है, और इसलिए यदि आप इसका उपयोग कर रहे हैं या कोई अन्य फ्रेमवर्क जो इस पर निर्भर करता है, Object.prototypeतो पहले से ही बढ़ाया जाएगा extend
ephemient

2
मेरा मतलब है कि तुम पर वीणा नहीं है, लेकिन यह कहना कि यह ठीक है क्योंकि प्रोटोटाइप। जेएस एक खराब तर्क है। Prototyp.js लोकप्रिय है, लेकिन इसका मतलब यह नहीं है कि वे जावास्क्रिप्ट कैसे करें पर रोल मॉडल हैं। जेएस समर्थक द्वारा प्रोटोटाइप लाइब्रेरी की इस विस्तृत समीक्षा की जाँच करें। dhtmlkitchen.com/?category=/JavaScript/&date=2008/06/17/…
SolutionYogi

7
अगर इसकी सही या गलत है तो देखभाल कौन करेगा? अगर यह काम करता है तो यह काम करता है। सही समाधान के लिए चारों ओर प्रतीक्षा करना एक अनुबंध को रखने, नए ग्राहकों को जीतने या समय सीमा को पूरा करने की कोशिश करने के अलावा बहुत अच्छा है। यहां किसी को भी दें, जो मुफ्त पैसे की प्रोग्रामिंग करने का शौक रखते हैं और वे अंततः सब कुछ "सही" तरीके से करेंगे।
डेविड

1
आप सभी लोग कहां पाए गए Object.prototype? Object.extendअपनी वस्तुओं के साथ हस्तक्षेप नहीं करेगा, यह सिर्फ एक Objectवस्तु के लिए एक समारोह देता है । और obj1.extend(obj2)आग समारोह का सही तरीका नहीं है, उपयोग Object.extend(obj1, obj2)insted
artnikpro

13

** विलय वस्तुओं का उपयोग करना आसान है Object.assignया प्रसार ...ऑपरेटर **

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

वस्तुओं को दाईं से बाईं ओर मर्ज किया जाता है, इसका मतलब यह है कि जिन वस्तुओं में उनके दाईं ओर ऑब्जेक्ट के समान गुण हैं, उन्हें ओवरराइड किया जाएगा।

इस उदाहरण में obj2.carओवरराइड होता हैobj1.car


12

बस अगर कोई Google बंद लाइब्रेरी का उपयोग कर रहा है :

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

समान सहायक फ़ंक्शन सरणी के लिए मौजूद है :

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'

10

मैंने डेविड कोलियर का तरीका बढ़ाया:

  • कई वस्तुओं के विलय की संभावना को जोड़ा
  • गहरी वस्तुओं का समर्थन करता है
  • ओवरराइड पैरामीटर (यदि अंतिम पैरामीटर बूलियन है, तो इसका पता लगाया जाता है)

यदि ओवरराइड झूठी है, तो कोई भी संपत्ति ओवरराइड नहीं होती है, लेकिन नए गुण जोड़े जाएंगे।

उपयोग: obj.merge (मर्ज ... [, ओवरराइड]);

यहाँ मेरा कोड है:

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

उदाहरण और टेस्टकेस:

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

मेरी बराबरी का तरीका यहाँ पाया जा सकता है: जावास्क्रिप्ट में वस्तु तुलना



9

में Ext जे एस 4 यह इस प्रकार के रूप में किया जा सकता है:

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

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

मर्ज (ऑब्जेक्ट) देखें : ऑब्जेक्ट


1
बग EXTJS-9173 के EXT.Object.bge से सावधान रहें क्योंकि अभी भी +2 साल बाद भी हल नहीं हुआ है
क्रिस

9

वाह .. यह पहला StackOverflow पोस्ट मैंने कई पृष्ठों के साथ देखा है। एक और "उत्तर" जोड़ने के लिए माफी

यह विधि ES5 & इससे पहले के लिए है - ES6 को संबोधित करने वाले अन्य उत्तर बहुत सारे हैं।

मैंने संपत्ति का उपयोग करने वाली किसी भी "गहरी" वस्तु का विलय नहीं देखा arguments। यहाँ मेरा जवाब है - कॉम्पैक्ट और पुनरावर्ती , असीमित वस्तु तर्क को पारित करने की अनुमति:

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

जिस हिस्से पर टिप्पणी की गई है वह वैकल्पिक है .. यह केवल उन तर्कों को छोड़ देगा जो ऑब्जेक्ट नहीं हैं (त्रुटियों को रोकते हुए)।

उदाहरण:

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

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

यह जवाब अब है लेकिन सागर में एक बूंद ...


सबसे छोटा जवाब जो महान काम करता है! यह अधिक उत्थान के योग्य है!
जेन्स टॉर्नेल

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

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

JQuery.extend () - लिंक का उपयोग करना

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

_.Merge () - लिंक का उपयोग करना

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

_.Extend () - लिंक का उपयोग करना

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

Object.assign () ECMAScript 2015 (ES6) का उपयोग करना - लिंक

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

सभी का उत्पादन

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

7

मार्कस ' और vsync' उत्तर के आधार पर , यह एक विस्तारित संस्करण है। फ़ंक्शन किसी भी तर्क को लेता है। इसका उपयोग DOM नोड्स पर गुण सेट करने के लिए किया जा सकता है और मूल्यों की गहरी प्रतियां बनाता है। हालाँकि, पहला तर्क संदर्भ द्वारा दिया गया है।

DOM नोड का पता लगाने के लिए, isDOMNode () फ़ंक्शन का उपयोग किया जाता है (देखें स्टैक ओवरफ़्लो प्रश्न JavaScript isDOM - यदि कोई जावास्क्रिप्ट ऑब्जेक्ट एक DOM ऑब्जेक्ट है ) तो आप कैसे चेक करेंगे?

यह ओपेरा 11, फ़ायरफ़ॉक्स 6, इंटरनेट एक्सप्लोरर 8 और Google क्रोम 16 में परीक्षण किया गया था ।

कोड

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

कुछ उदाहरण

आंतरिक HTML और HTML तत्व की शैली सेट करें

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

सरणियों और वस्तुओं को मिलाएं। ध्यान दें कि अपरिभाषित का उपयोग बाएं खंड सरणी / ऑब्जेक्ट में मानों को संरक्षित करने के लिए किया जा सकता है।

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

जावास्क्रिप्ट ऑब्जेक्ट (नल सहित) को न करने वाले किसी भी तर्क की अनदेखी की जाएगी। पहले तर्क को छोड़कर, DOM नोड्स को भी छोड़ दिया जाता है। खबरदार है कि स्ट्रिंग्स, नए स्ट्रिंग की तरह बनाया () वास्तव में वस्तुओं में हैं।

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

यदि आप पहली दलील के रूप में दो वस्तुओं को एक नए (दो में से किसी को प्रभावित किए बिना) आपूर्ति {} में विलय करना चाहते हैं

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

संपादित करें (रीपरस्पून द्वारा):

सरणियों को मर्ज करने के लिए भी

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


5

आप lodash के उपयोग करना चाहिए defaultsDeep

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

5

Underscore.js के साथ , वस्तुओं की एक सरणी को मर्ज करने के लिए:

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

यह परिणाम है:

Object {a: 1, b: 2, c: 3, d: 4}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.