MyObj.hasOwnProperty (प्रोप) के बजाय Object.prototype.hasOwnProperty.call (myObj, Prop) का उपयोग क्यों करें?


104

अगर मैं सही ढंग से समझता हूं, तो जावास्क्रिप्ट में प्रत्येक वस्तु ऑब्जेक्ट प्रोटोटाइप से विरासत में मिली है, जिसका अर्थ है कि जावास्क्रिप्ट में प्रत्येक और हर वस्तु की अपनी प्रोटोटाइप श्रृंखला के माध्यम से hasOwnProperty फ़ंक्शन तक पहुंच है।

आवश्यकता पढ़ते समय। स्रोत कोड, मैं इस समारोह पर ठोकर खाई:

function hasProp(obj, prop) {
    return hasOwn.call(obj, prop);
}

hasOwnके लिए एक संदर्भ है Object.prototype.hasOwnProperty। क्या इस फ़ंक्शन को लिखने का कोई व्यावहारिक अंतर है

function hasProp(obj, prop) {
    return obj.hasOwnProperty(prop);
}

और जब से हम इस पर हैं, हम इस समारोह को क्यों परिभाषित करते हैं? क्या यह (मामूली) प्रदर्शन लाभ के लिए संपत्ति के उपयोग के शॉर्टकट और स्थानीय कैशिंग का सवाल है, या क्या मैं किसी भी मामले को याद कर रहा हूं जहां hasOwnProperty का उपयोग उन वस्तुओं पर किया जा सकता है जिनके पास यह विधि नहीं है?

जवाबों:


109

क्या कोई व्यावहारिक अंतर है [मेरे उदाहरणों के बीच]?

उपयोगकर्ता के पास एक जावास्क्रिप्ट ऑब्जेक्ट हो सकता है Object.create(null), जिसके साथ एक null [[Prototype]]श्रृंखला होगी, और इसलिए उस पर hasOwnProperty()उपलब्ध नहीं होगा । अपने दूसरे रूप का उपयोग करना इस कारण से काम नहीं कर पाएगा।

यह Object.prototype.hasOwnProperty()(और भी कम) के लिए एक सुरक्षित संदर्भ है ।

आप सोच सकते हैं कि किसी ने किया होगा ...

var someObject = {
    hasOwnProperty: function(lol) {
        return true;
    }
};

जो hasProp(someObject)असफल हो जाता है, उसे आपके दूसरे उदाहरण की तरह लागू किया गया था (यह उस विधि को सीधे ऑब्जेक्ट पर खोजेगा और उस स्थान को लागू करेगा, बजाय कि उसे सौंप दिया जाएगा Object.prototype.hasOwnProperty)।

लेकिन इसकी संभावना कम हो किसी को ओवरराइड होगा है Object.prototype.hasOwnPropertyसंदर्भ।

और जब से हम इस पर हैं, हम इस समारोह को क्यों परिभाषित करते हैं?

ऊपर देखो।

क्या यह (मामूली) प्रदर्शन लाभ के लिए संपत्ति के उपयोग के शॉर्टकट और स्थानीय कैशिंग का सवाल है ...

यह इसे सिद्धांत रूप में तेज कर सकता है, क्योंकि [[Prototype]]श्रृंखला का पालन नहीं करना पड़ता है, लेकिन मुझे संदेह है कि यह नगण्य है और कार्यान्वयन के कारण का कारण नहीं है।

... या मैं ऐसे किसी भी मामले को याद नहीं कर रहा हूँ जहाँ hasOwnPropertyउन वस्तुओं पर उपयोग किया जा सकता है जिनमें यह विधि नहीं है?

hasOwnProperty()पर मौजूद है Object.prototype, लेकिन ओवरराइड किया जा सकता है। प्रत्येक मूल जावास्क्रिप्ट ऑब्जेक्ट (लेकिन होस्ट ऑब्जेक्ट्स को इसका पालन करने की गारंटी नहीं है, देखें कि रॉब की इन-डेप्थ स्पष्टीकरण ) Object.prototypeश्रृंखला पर इसकी अंतिम वस्तु के रूप में है null( इससे पहले कि ऑब्जेक्ट द्वारा लौटाए गए कोर्स के लिए छोड़कर Object.create(null))।


आपका तर्क शायद सही है, लेकिन मुझे लगता है कि आप दयालु हैं। यदि आवश्यकता के लेखकों को लगता है कि hasOwnProperty को ओवरराइड किया गया है (जो कि बहुत कम संभावना है), तो उन्हें सभी बिल्ट-इन तरीकों को कॉल करना चाहिए जो कि शायद (शायद वे करते हैं)।
रॉब

@Periback सच में? मुझे पूरा यकीन था कि इसने इसका समर्थन किया था।
एलेक्स

ES6 शॉर्टकट यदि अक्सर उपयोग किया जाता है। const hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
रिचर्ड अयोटे

15

अगर मैं सही ढंग से समझूं, तो जावास्क्रिप्ट में प्रत्येक वस्तु ऑब्जेक्ट प्रोटोटाइप से विरासत में मिली है

यह बालों को विभाजित करने की तरह लग सकता है, लेकिन जावास्क्रिप्ट (ECMAScript कार्यान्वयन के लिए सामान्य शब्द) और ECMAScript (जावास्क्रिप्ट कार्यान्वयन के लिए प्रयुक्त भाषा ) के बीच अंतर है । यह ECMAScript है जो एक विरासत योजना को परिभाषित करता है, जावास्क्रिप्ट नहीं, इसलिए केवल मूल ECMAScript ऑब्जेक्ट्स को उस विरासत योजना को लागू करने की आवश्यकता होती है।

एक रनिंग जावास्क्रिप्ट प्रोग्राम में कम से कम बिल्ट-इन ECMAScript ऑब्जेक्ट्स (ऑब्जेक्ट, फंक्शन, नंबर इत्यादि) होते हैं और शायद कुछ देशी ऑब्जेक्ट्स (जैसे फ़ंक्शंस)। इसमें कुछ होस्ट ऑब्जेक्ट भी हो सकते हैं (जैसे ब्राउज़र में DOM ऑब्जेक्ट, या अन्य होस्ट वातावरण में अन्य ऑब्जेक्ट)।

जबकि अंतर्निहित और देशी वस्तुओं को ECMA-262 में परिभाषित विरासत योजना को लागू करना चाहिए, मेजबान ऑब्जेक्ट नहीं करते हैं। इसलिए, जावास्क्रिप्ट वातावरण में सभी ऑब्जेक्ट्स Object.prototyp से इनहेरिट नहीं किए जाने चाहिए । उदाहरण के लिए, IE में होस्ट ऑब्जेक्ट्स को ActiveX ऑब्जेक्ट्स के रूप में कार्यान्वित किया जाता है यदि देशी ऑब्जेक्ट्स के रूप में व्यवहार किया जाता है (इसलिए क्यों प्रयास करें..कैसे MS XMLHttpRequest ऑब्जेक्ट्स को इनिशियलाइज़ करने के लिए उपयोग किया जाता है)। कुछ डोम ऑब्जेक्ट्स (जैसे IE में क्वॉडक मोड में NodeLists) यदि एरे तरीकों से पास किए गए हैं, तो त्रुटियों को फेंक दिया जाएगा, IE 8 और लोअर में डोम ऑब्जेक्ट्स में एक ECMAScript- इनहेरिटेंस स्कीम नहीं है, और इसी तरह।

इसलिए यह नहीं माना जाना चाहिए कि एक जावास्क्रिप्ट पर्यावरण में सभी वस्तुएं Object.prototype से विरासत में मिली हैं।

जिसका अर्थ है कि जावास्क्रिप्ट में प्रत्येक वस्तु की अपनी प्रोटोटाइप श्रृंखला के माध्यम से hasOwnProperty फ़ंक्शन तक पहुंच है

जो कि quirks मोड में IE में कुछ होस्ट ऑब्जेक्ट्स के लिए सही नहीं है (और IE 8 और हमेशा कम)।

उपरोक्त को देखते हुए, यह सोचने योग्य है कि किसी वस्तु की अपनी स्वयं की hasOwProProperty विधि क्यों हो सकती है और पहले परीक्षण के बजाय कुछ अन्य hasOwnProperty पद्धति को कॉल करने की सलाह दी जाती है यदि यह एक अच्छा विचार है या नहीं।

संपादित करें

मुझे संदेह है कि उपयोग करने का कारण Object.prototype.hasOwnProperty.callयह है कि कुछ ब्राउज़रों में, होस्ट ऑब्जेक्ट में एक hasOwnProperty विधि नहीं है , कॉल का उपयोग करके और अंतर्निहित विधि एक विकल्प है। हालाँकि, ऐसा करना सामान्य रूप से उपरोक्त कारणों के लिए एक अच्छा विचार नहीं लगता है।

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

var o = document.getElementsByTagName('foo');

// false in most browsers, throws an error in IE 6, and probably 7 and 8
o.hasOwnProperty('bar');

// false in all browsers
('bar' in o);

// false (in all browsers? Do some throw errors?)
Object.prototype.hasOwnProperty.call(o, 'bar');

एक विकल्प (IE6 और अन्य में परीक्षण किया गया):

function ownProp(o, prop) {

  if ('hasOwnProperty' in o) {
    return o.hasOwnProperty(prop);

  } else {
    return Object.prototype.hasOwnProperty.call(o, prop);
  }
}

इस तरह से आप केवल विशेष रूप से अंतर्निहित hasOwnProperty को कॉल करते हैं जहां ऑब्जेक्ट के पास यह नहीं है (विरासत में या अन्यथा)।

हालाँकि, यदि किसी ऑब्जेक्ट में कोई hasOwnPropertyविधि नहीं है , तो यह संभवतः ऑपरेटर के रूप में उपयोग करने के लिए उपयुक्त है क्योंकि ऑब्जेक्ट की संभावना एक उत्तराधिकार योजना नहीं है और सभी गुण ऑब्जेक्ट पर हैं (हालांकि यह केवल एक धारणा है), जैसे प्रॉपर्टी के लिए DOM ऑब्जेक्ट सपोर्ट के परीक्षण में ऑपरेटर एक सामान्य (और प्रतीत होता है सफल) तरीका है।


धन्यवाद। Object.prototype.hasOwnProperty.call (ओ, 'बार') एफएफ 18.0 (कम से कम मेरे मामले में) में काम नहीं कर रहा है। इसलिए मैंने उपयोग करने का फैसला किया ('बार' ओ में) - और इससे मदद मिली।
मैक्स

@ मोम लुकअप inनहीं करता है hasOwnProperty(), मुझे संदेह है कि जिस प्रॉपर्टी की आपको तलाश थी वह प्रोटोटाइप चेन पर मौजूद थी।
एलेक्स

यह eslint.org/docs/rules/no-prototype-builtins से एक दिलचस्प उदाहरण है : उदाहरण के लिए, एक वेबसर्वर के लिए एक क्लाइंट से JSON इनपुट पार्स करना और hasOwnPropertyपरिणामी वस्तु पर सीधे कॉल करना असुरक्षित होगा , क्योंकि एक दुर्भावनापूर्ण ग्राहक हो सकता है JSON मान भेजें {"hasOwnProperty": 1}और सर्वर को क्रैश करने का कारण बनें।
n

ज़रूर, लेकिन इस तरह के मुद्दों को रोकने के लिए JSON स्कीमा के साथ किसी भी क्लाइंट-आपूर्ति किए गए JSON को परीक्षण या मान्य करने में समझदारी होगी, भले ही आपकी चिंता सिर्फ डेटा गुणवत्ता की हो। और इससे सर्वर क्रैश नहीं होना चाहिए। :-)
रोबग

8

जावास्क्रिप्ट संपत्ति के नाम की रक्षा नहीं करता है hasOwProperty

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

आप बेहतर समझ पाने के लिए अपने ब्राउज़र कंसोल के नीचे दिए गए कोड स्निपेट्स को कॉपी कर सकते हैं

var foo = {
  hasOwnProperty: function() {
    return false;
  },
  bar: 'I belong to foo'
};

हमेशा झूठा लौटता है

foo.hasOwnProperty('bar'); // false

किसी अन्य ऑब्जेक्ट की hasOwnProperty का उपयोग करें और इसे foo के लिए इस सेट के साथ कॉल करें

({}).hasOwnProperty.call(foo, 'bar'); // true

इस उद्देश्य के लिए ऑब्जेक्ट प्रोटोटाइप से hasOwnProperty प्रॉपर्टी का उपयोग करना भी संभव है

Object.prototype.hasOwnProperty.call(foo, 'bar'); // true

1
आप जो बिंदु बना रहे हैं वह पहले से ही स्वीकृत उत्तर में बनाया गया है , सिवाय इसके कि hasOwnPropertyरिटर्न का ओवरराइड true
लुई

1

दोनों मौजूदा जवाबों में दी गई जानकारी हाजिर है। हालाँकि, का उपयोग:

('propertyName' in obj)

कुछ समय का उल्लेख है। यह ध्यान दिया जाना चाहिए कि hasOwnPropertyकार्यान्वयन केवल तभी वापस होगा जब संपत्ति सीधे परीक्षण की जा रही वस्तु पर निहित हो।

inऑपरेटर भी प्रोटोटाइप श्रृंखला के माध्यम से नीचे निरीक्षण करेंगे।

इसका मतलब यह है कि उदाहरण की प्रॉपर्टीज तब वापस लौटेगी जब पास की hasOwnPropertyगई प्रॉपर्टीज गलत हो जाएगी।

inऑपरेटर का उपयोग करके उदाहरण और प्रोटोटाइप दोनों गुण सही वापस आ जाएंगे।

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