लोदाश - .extend () / .ignign () और .merge () के बीच अंतर


जवाबों:


582

यहां बताया गया है कि कैसे extend/ assignकाम करता है: स्रोत में प्रत्येक संपत्ति के लिए, गंतव्य के रूप में इसके मूल्य की प्रतिलिपि बनाएँ। यदि संपत्ति के मूल्य स्वयं वस्तु हैं, तो उनके गुणों का कोई पुनरावृत्ति नहीं है। संपूर्ण वस्तु को स्रोत से लिया जाएगा और गंतव्य के लिए सेट किया जाएगा।

यहां बताया गया है कि कैसे mergeकाम करता है: स्रोत में प्रत्येक संपत्ति के लिए, जांचें कि क्या संपत्ति स्वयं वस्तु है। यदि यह फिर से नीचे जा रहा है और स्रोत से गंतव्य तक चाइल्ड ऑब्जेक्ट गुणों को मैप करने का प्रयास करें। इसलिए अनिवार्य रूप से हम ऑब्जेक्ट पदानुक्रम को स्रोत से गंतव्य तक मर्ज करते हैं। के लिए एक ओर जहां extend/ assign, यह स्रोत से गंतव्य के लिए संपत्तियों की साधारण एक स्तर प्रति है।

यहाँ सरल JSBin है जो इस क्रिस्टल को स्पष्ट करेगा: http://jsbin.com/uXaqIMa/2/edit?js,console

यहाँ अधिक विस्तृत संस्करण है जिसमें उदाहरण के साथ सरणी भी शामिल है: http://jsbin.com/uXaqIMa/1/edit?js,console


16
एक महत्वपूर्ण अंतर यह प्रतीत होता है कि जबकि _.merge एक नई मर्ज की गई वस्तु लौटाता है, _.extend गंतव्य ऑब्जेक्ट को इन-प्लेस में बदल देता है,
letronje

69
वे दोनों गंतव्य ऑब्जेक्ट को म्यूट करने के लिए प्रकट होते हैं, भले ही वे वापस लौट आए।
जेसन राइस

7
यह भी प्रतीत होता है कि _.extend गंतव्य ऑब्जेक्ट के क्लोबर्स सदस्य हैं यदि वे स्रोत ऑब्जेक्ट में मौजूद नहीं हैं, जो मुझे आश्चर्यचकित कर रहा है।
जेसन राइस

5
@JasonRice वे लता नहीं मिलता है। इस फिडेल में उदाहरण के लिए, "a" प्रॉपर्टी क्लोबर्ड नहीं होती है । यह सच है कि विस्तार के बाद, गंतव्य ["p"] ["y"] अब मौजूद नहीं है - इसका कारण यह है कि विस्तार src से पहले और भाग्य दोनों में एक "p" गुण था, इसलिए भाग्य की "p" संपत्ति पूरी तरह से अधिलेखित हो जाती है src की "p" संपत्ति के द्वारा (वे अब ठीक उसी वस्तु हैं)।
केविन व्हीलर

14
स्पष्ट होने के लिए, दोनों विधियाँ संदर्भ द्वारा पहले तर्क को संशोधित / अधिलेखित करती हैं । इसलिए यदि आप परिणामी मर्ज से एक नई वस्तु चाहते हैं, तो एक वस्तु शाब्दिक रूप से पास करना सबसे अच्छा है। var combined = merge({}, src, dest)
जॉन जैक्स

534

लोदाश संस्करण 3.10.1

तुलना के तरीके

  • _.merge(object, [sources], [customizer], [thisArg])
  • _.assign(object, [sources], [customizer], [thisArg])
  • _.extend(object, [sources], [customizer], [thisArg])
  • _.defaults(object, [sources])
  • _.defaultsDeep(object, [sources])

समानताएँ

  • उनमें से कोई भी सरणियों पर काम नहीं करता है जैसा कि आप उम्मीद कर सकते हैं
  • _.extendके लिए एक उपनाम है _.assign, इसलिए वे समान हैं
  • वे सभी लक्ष्य वस्तु (पहले तर्क) को संशोधित करते प्रतीत होते हैं
  • nullवही सब संभालते हैं

मतभेद

  • _.defaultsऔर _.defaultsDeepदूसरों की तुलना में रिवर्स ऑर्डर में तर्कों को संसाधित करता है (हालांकि पहला तर्क अभी भी लक्ष्य वस्तु है)
  • _.mergeऔर _.defaultsDeepबाल वस्तुओं को मर्ज कर देगा और अन्य मूल स्तर पर अधिलेखित हो जाएंगे
  • केवल _.assignऔर के _.extendसाथ एक मान को अधिलेखित कर देगाundefined

टेस्ट

वे सभी समान तरीके से सदस्यों को रूट पर संभालते हैं।

_.assign      ({}, { a: 'a' }, { a: 'bb' }) // => { a: "bb" }
_.merge       ({}, { a: 'a' }, { a: 'bb' }) // => { a: "bb" }
_.defaults    ({}, { a: 'a' }, { a: 'bb' }) // => { a: "a"  }
_.defaultsDeep({}, { a: 'a' }, { a: 'bb' }) // => { a: "a"  }

_.assignसंभालता है undefinedलेकिन अन्य इसे छोड़ देंगे

_.assign      ({}, { a: 'a'  }, { a: undefined }) // => { a: undefined }
_.merge       ({}, { a: 'a'  }, { a: undefined }) // => { a: "a" }
_.defaults    ({}, { a: undefined }, { a: 'bb' }) // => { a: "bb" }
_.defaultsDeep({}, { a: undefined }, { a: 'bb' }) // => { a: "bb" }

वे सभी nullउसी को संभालते हैं

_.assign      ({}, { a: 'a'  }, { a: null }) // => { a: null }
_.merge       ({}, { a: 'a'  }, { a: null }) // => { a: null }
_.defaults    ({}, { a: null }, { a: 'bb' }) // => { a: null }
_.defaultsDeep({}, { a: null }, { a: 'bb' }) // => { a: null }

लेकिन केवल _.mergeऔर _.defaultsDeepबाल वस्तुओं का विलय होगा

_.assign      ({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "b": "bb" }}
_.merge       ({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "a": "a", "b": "bb" }}
_.defaults    ({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "a": "a" }}
_.defaultsDeep({}, {a:{a:'a'}}, {a:{b:'bb'}}) // => { "a": { "a": "a", "b": "bb" }}

और उनमें से कोई भी सरणियों का विलय नहीं करेगा ऐसा लगता है

_.assign      ({}, {a:['a']}, {a:['bb']}) // => { "a": [ "bb" ] }
_.merge       ({}, {a:['a']}, {a:['bb']}) // => { "a": [ "bb" ] }
_.defaults    ({}, {a:['a']}, {a:['bb']}) // => { "a": [ "a"  ] }
_.defaultsDeep({}, {a:['a']}, {a:['bb']}) // => { "a": [ "a"  ] }

सभी लक्ष्य वस्तु को संशोधित करते हैं

a={a:'a'}; _.assign      (a, {b:'bb'}); // a => { a: "a", b: "bb" }
a={a:'a'}; _.merge       (a, {b:'bb'}); // a => { a: "a", b: "bb" }
a={a:'a'}; _.defaults    (a, {b:'bb'}); // a => { a: "a", b: "bb" }
a={a:'a'}; _.defaultsDeep(a, {b:'bb'}); // a => { a: "a", b: "bb" }

कोई भी वास्तव में सरणियों पर अपेक्षित रूप से काम नहीं करता है

नोट: जैसा कि @ मिस्टिक ने बताया है, लॉडेज एरेज़ को ऑब्जेक्ट्स के रूप में मानता है, जहाँ कुंजियाँ इंडेक्स हैं।

_.assign      ([], ['a'], ['bb']) // => [ "bb" ]
_.merge       ([], ['a'], ['bb']) // => [ "bb" ]
_.defaults    ([], ['a'], ['bb']) // => [ "a"  ]
_.defaultsDeep([], ['a'], ['bb']) // => [ "a"  ]

_.assign      ([], ['a','b'], ['bb']) // => [ "bb", "b" ]
_.merge       ([], ['a','b'], ['bb']) // => [ "bb", "b" ]
_.defaults    ([], ['a','b'], ['bb']) // => [ "a", "b"  ]
_.defaultsDeep([], ['a','b'], ['bb']) // => [ "a", "b"  ]

31
यह वास्तव में सरणियों का विलय करता है ठीक उसी तरह जैसे यह वस्तुओं को मिलाता है, क्योंकि सरणियां संख्यात्मक कुंजियों वाली वस्तुएं हैं। मैं सहमत हूं कि किसी को सरणियों को बदलने या बदलने की उम्मीद होगी, उपयोग पर निर्भर करता है।
मिस्त्री

11
बहुत बढ़िया जवाब। परीक्षण बहुत ही विवादास्पद थे :-)
लुसियो पावा

5
_.extend is an alias for _.assign, so they are identicalके साथ संघर्षOnly _.assign will overwrite a value with undefined
Chazt3n

9
V4.0 के रूप में, _.extend अब _.assignIn के लिए एक उपनाम है, _assign नहीं। असाइनमेंट फ़ंक्शन विरासत में मिली संपत्तियों के साथ काम करता है।
माइक हेडमैन

2
क्या अशक्त को यहाँ अपरिभाषित माना जाता है?
C_B

75

undefinedमूल्यों पर ध्यान देने के लिए एक और अंतर है :

mergeInto = { a: 1}
toMerge = {a : undefined, b:undefined}
lodash.extend({}, mergeInto, toMerge) // => {a: undefined, b:undefined}
lodash.merge({}, mergeInto, toMerge)  // => {a: 1, b:undefined}

तो मूल्यों को परिभाषित मूल्यों में mergeविलय नहीं करेगा undefined


3
क्या यह सिर्फ मैं या वह करता है जो लॉश को पूरा करता है। यह पूरी तरह से बेकार है कि यह हमेशा 'टॉमर' ऑब्जेक्ट का क्लोन देता है?
जेसन राइस

6
अगर ऐसी mergeIntoसंपत्तियां थीं जो toMergeउनके पास नहीं थीं , तो यह उन संपत्तियों को बनाए रखेगा। उस मामले में यह एक क्लोन नहीं होगा।
डेविड निएले

1
@JasonRice खाली {} को हटा दें और इसे लॉज में जगह में विलय कर देगा।
sidonaldson

20

यह विचार करने में मददगार हो सकता है कि वे शब्दार्थ से क्या करते हैं:

_.assign

   will assign the values of the properties of its second parameter and so on,
   as properties with the same name of the first parameter. (shallow copy & override)

_.merge

   merge is like assign but does not assign objects but replicates them instead.
  (deep copy)

_.defaults

   provides default values for missing values.
   so will assign only values for keys that do not exist yet in the source.

_.defaultsDeep

   works like _defaults but like merge will not simply copy objects
   and will use recursion instead.

मेरा मानना ​​है कि शब्दार्थ से उन तरीकों के बारे में सोचना सीखने से आप बेहतर "अनुमान" लगा सकते हैं कि मौजूदा और गैर-मौजूदा मूल्यों के सभी विभिन्न परिदृश्यों के लिए व्यवहार क्या होगा।


3

यदि आप एक ही objसंदर्भ को बनाए रखते हुए ओवरराइड के बिना एक गहरी प्रतिलिपि चाहते हैं

obj = _.assign(obj, _.merge(obj, [source]))

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.