javascript JQuery की विस्तार विधि के बराबर जावास्क्रिप्ट




object extend (7)

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

पृष्ठभूमि

मेरे पास एक ऐसा फ़ंक्शन है जो config ऑब्जेक्ट को तर्क के रूप में लेता है। फ़ंक्शन के भीतर, मेरे पास default ऑब्जेक्ट भी है। उन वस्तुओं में से प्रत्येक में वे गुण होते हैं जो फ़ंक्शन के भीतर शेष कोड के लिए अनिवार्य रूप से सेटिंग्स के रूप में कार्य करते हैं। config ऑब्जेक्ट के भीतर सभी सेटिंग्स को निर्दिष्ट करने से रोकने के लिए, मैं एक नई ऑब्जेक्ट को भरने के लिए jQuery की extend विधि का उपयोग करता extend , default ऑब्जेक्ट से किसी भी डिफ़ॉल्ट मान के साथ settings अगर उन्हें config ऑब्जेक्ट में निर्दिष्ट नहीं किया गया था:

var config = {key1: value1};
var default = {key1: default1, key2: default2, key 3: default 3};

var settings = $.extend(default, config);

//resulting properties of settings:
settings = {key1: value1, key2: default2, key 3: default 3};

मुसीबत

यह बहुत अच्छा काम करता है, लेकिन मैं jQuery की आवश्यकता के बिना इस कार्यक्षमता को पुन: पेश करना चाहता हूं। क्या सादा ओल 'जावास्क्रिप्ट के साथ ऐसा करने के लिए एक समान रूप से सुरुचिपूर्ण (या नज़दीक) माध्यम है?

संपादित करें: गैर डुप्लिकेट औचित्य

यह प्रश्न " दो जावास्क्रिप्ट ऑब्जेक्ट्स के गुणों को गतिशील रूप से कैसे विलय कर सकता है? " प्रश्न का डुप्लिकेट नहीं है। जबकि वह प्रश्न केवल एक ऑब्जेक्ट बनाना चाहता है जिसमें दो अलग-अलग ऑब्जेक्ट्स से सभी चाबियाँ और मान शामिल हैं - मैं विशेष रूप से यह जानना चाहता हूं कि इस ऑब्जेक्ट में यह कैसे करना है कि दोनों ऑब्जेक्ट्स कुछ साझा करते हैं लेकिन सभी चाबियाँ नहीं हैं और कौन सा ऑब्जेक्ट प्राथमिकता प्राप्त करेगा ( डिफ़ॉल्ट) परिणामस्वरूप ऑब्जेक्ट के लिए डुप्लीकेट कुंजी हैं। और इससे भी अधिक विशेष रूप से, मैं इसे प्राप्त करने के लिए jQuery की विधि के उपयोग को संबोधित करना चाहता था और jQuery के बिना ऐसा करने का वैकल्पिक तरीका ढूंढना चाहता था। जबकि दोनों सवालों के कई जवाब ओवरलैप हैं, इसका मतलब यह नहीं है कि प्रश्न स्वयं एक जैसे हैं।



यह एक jQuery निर्भरता को खत्म करने की कोशिश करते समय गहरी प्रतिलिपि के साथ मेरा थोड़ा अलग दृष्टिकोण है। यह ज्यादातर छोटे होने के लिए डिज़ाइन किया गया है, इसलिए इसमें सभी सुविधाओं की अपेक्षा नहीं हो सकती है। पूरी तरह ES5- संगत होना चाहिए ( Object.keys उपयोग के कारण IE9 से शुरू होना चाहिए):

function extend(obj1, obj2) {
    var keys = Object.keys(obj2);
    for (var i = 0; i < keys.length; i += 1) {
      var val = obj2[keys[i]];
      obj1[keys[i]] = ['string', 'number', 'array', 'boolean'].indexOf(typeof val) === -1 ? extend(obj1[keys[i]] || {}, val) : val;
    }
    return obj1;
  }

आप सोच सकते हैं कि पांचवीं पंक्ति वास्तव में क्या करती है ... यदि obj2.key एक ऑब्जेक्ट शाब्दिक है (यानी यदि यह कोई साधारण प्रकार नहीं है) तो हम इसे फिर से कॉल करते हैं। अगर उस नाम वाली संपत्ति obj1 में अभी तक मौजूद नहीं है, तो हम इसे पहले एक खाली ऑब्जेक्ट में प्रारंभ करते हैं। अन्यथा हम obj1.key को obj2.key पर सेट करते हैं।

यहां मेरे कुछ मोचा / चाई परीक्षण हैं जो सामान्य मामलों को यहां काम करने के लिए साबित करना चाहिए:

it('should extend a given flat object with another flat object', () => {
  const obj1 = {
    prop1: 'val1',
    prop2: 42,
    prop3: true,
    prop4: 20.16,
  };
  const obj2 = {
    prop4: 77.123,
    propNew1: 'newVal1',
    propNew2: 71,
  };
  assert.deepEqual(utils.extend(obj1, obj2), {
    prop1: 'val1',
    prop2: 42,
    prop3: true,
    prop4: 77.123,
    propNew1: 'newVal1',
    propNew2: 71,
  });
});

it('should deep-extend a given flat object with a nested object', () => {
  const obj1 = {
    prop1: 'val1',
    prop2: 'val2',
  };
  const obj2 = {
    propNew1: 'newVal1',
    propNew2: {
      propNewDeep1: 'newDeepVal1',
      propNewDeep2: 42,
      propNewDeep3: true,
      propNewDeep4: 20.16,
    },
  };
  assert.deepEqual(utils.extend(obj1, obj2), {
    prop1: 'val1',
    prop2: 'val2',
    propNew1: 'newVal1',
    propNew2: {
      propNewDeep1: 'newDeepVal1',
      propNewDeep2: 42,
      propNewDeep3: true,
      propNewDeep4: 20.16,
    },
  });
});

it('should deep-extend a given nested object with another nested object and deep-overwrite members', () => {
  const obj1 = {
    prop1: 'val1',
    prop2: {
      propDeep1: 'deepVal1',
      propDeep2: 42,
      propDeep3: true,
      propDeep4: {
        propDeeper1: 'deeperVal1',
        propDeeper2: 777,
        propDeeper3: 'I will survive',
      },
    },
    prop3: 'lone survivor',
  };
  const obj2 = {
    prop1: 'newVal1',
    prop2: {
      propDeep1: 'newDeepVal1',
      propDeep2: 84,
      propDeep3: false,
      propDeep4: {
        propDeeper1: 'newDeeperVal1',
        propDeeper2: 888,
      },
    },
  };
  assert.deepEqual(utils.extend(obj1, obj2), {
    prop1: 'newVal1',
    prop2: {
      propDeep1: 'newDeepVal1',
      propDeep2: 84,
      propDeep3: false,
      propDeep4: {
        propDeeper1: 'newDeeperVal1',
        propDeeper2: 888,
        propDeeper3: 'I will survive',
      },
    },
    prop3: 'lone survivor',
  });
});

मैं इस कार्यान्वयन पर फीडबैक या टिप्पणियों के बारे में खुश हूं। अग्रिम में धन्यवाद!


इवान कुकर के दृष्टिकोण को भी एक नया ऑब्जेक्ट प्रोटोटाइप बनाने के लिए अनुकूलित किया जा सकता है:

Object.prototype.extend = function(b){
for(var key in b)
    if(b.hasOwnProperty(key))
        this[key] = b[key];
    return this;
}

var settings = default.extend(config);

जब मैं शुद्ध जावास्क्रिप्ट के साथ विकसित होता हूं तो यह मुझे बहुत मदद करता है।

function extends(defaults, selfConfig){
     selfConfig = JSON.parse(JSON.stringify(defaults));
     for (var item in config) {
         if (config.hasOwnProperty(item)) {
             selfConfig[item] = config[item];
         }
     }
     return selfConfig;
}

आप कथन के for ऑब्जेक्ट के गुणों के माध्यम से पाश कर सकते हैं।

var settings = extend(default, config);

function extend(a, b){
    var c = {};
    for(var p in a)
        c[p] = (b[p] == null) ? a[p] : b[p];
    return c;
}

मैं इस कोड को पसंद करता हूं जो मेरे सामान्य के लिए उपयोग करता है, और पहली वस्तु को उलझन में नहीं डालता है:

function forEachIn(obj, fn) {
    var index = 0;
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            fn(obj[key], key, index++);
        }
    }
}

function extend() {
    var result = {};
    for (var i = 0; i < arguments.length; i++) {
        forEachIn(arguments[i],
            function(obj, key) {
                result[key] = obj;
            });
    }
    return result;
}

यदि आप वास्तव में सामान को पहली वस्तु में मर्ज करना चाहते हैं, तो आप यह कर सकते हैं:

obj1 = extend(obj1, obj2);

अपने कोड में परिणाम प्राप्त करने के लिए, आप करेंगे:

function extend(a, b){
    for(var key in b)
        if(b.hasOwnProperty(key))
            a[key] = b[key];
    return a;
}

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

$.extend({}, default, config)

एक और मजबूत समाधान जो jQuery की कार्यक्षमता की नकल करता है, निम्नानुसार होगा:

function extend(){
    for(var i=1; i<arguments.length; i++)
        for(var key in arguments[i])
            if(arguments[i].hasOwnProperty(key))
                arguments[0][key] = arguments[i][key];
    return arguments[0];
}




extend