दिलचस्प पोस्ट
homebrew OSX पर काम नहीं कर रहा है AsyncTask और Looper.prepare () त्रुटि क्या प्रति पृष्ठ में ViewPager के कई दृश्य हो सकते हैं? 'स्व' के साथ संपत्तियों का उपयोग कब करना है Runtime.getRuntime ()। कार्यकारी () बैच फ़ाइल में स्टडिन स्ट्रीम पढ़ें जावा: एक पाठ फ़ाइल कैसे पढ़ा जाए फ़ाइल _get_contents क्यों काम नहीं करता है? मैक ओएस एक्स पर पोस्टग्रेएसक्यूएल सर्वर कैसे शुरू करें? XML पर JSON को पसंद करते समय? यह कैसे पता चलेगा कि फाइल कॉपीिंग 'प्रगति में है' / जावा में पूर्ण (1.6) क्या HTTP बुनियादी प्रमाणीकरण के लिए मुझे एन्कोडिंग का उपयोग करना चाहिए? एनजी-क्लिक एक निर्देश के टेम्पलेट के भीतर काम नहीं करता एक्सेल VBA पीडीएफ को चयनित शीट निर्यात करने के लिए क्या git alias द्वारा git कमांड ओवरराइड करना संभव है?

कॉलबैक के अंदर सही `यह` कैसे पहुंचें?

मेरे पास कन्स्ट्रक्टर फ़ंक्शन है जो एक ईवेंट हैंडलर पंजीकृत करता है:

हालांकि, मैं कॉलबैक के अंदर निर्मित ऑब्जेक्ट की data प्रॉपर्टी का उपयोग नहीं कर पा रहा हूं। ऐसा लगता है कि this उस ऑब्जेक्ट का उल्लेख नहीं करता है जो बनाया गया था, लेकिन किसी दूसरे को।

मैंने एक अनाम फ़ंक्शन के बजाय एक ऑब्जेक्ट विधि का उपयोग करने की भी कोशिश की:

 function MyConstructor(data, transport) { this.data = data; transport.on('data', this.alert); } MyConstructor.prototype.alert = function() { alert(this.name); }; 

लेकिन यह एक ही समस्याएं दर्शाती है

मैं सही वस्तु कैसे प्राप्त कर सकता हूं?

Solutions Collecting From Web of "कॉलबैक के अंदर सही `यह` कैसे पहुंचें?"

आपको इसके बारे में क्या पता होना चाहिए

this (उर्फ "संदर्भ") प्रत्येक फ़ंक्शन के अंदर एक विशेष कीवर्ड है और इसकी वैल्यू केवल इस बात पर निर्भर करती है कि फ़ंक्शन कैसे बुलाया गया था, यह नहीं कि कैसे / जब / जहां यह परिभाषित किया गया था। यह अन्य वर्णों की तरह, लेक्सिकल गुंजाइश से प्रभावित नहीं है। यहाँ कुछ उदाहरण हैं:

 function foo() { console.log(this); } // normal function call foo(); // `this` will refer to `window` // as object method var obj = {bar: foo}; obj.bar(); // `this` will refer to `obj` // as constructor function new foo(); // `this` will refer to an object that inherits from `foo.prototype` 

इसके बारे में अधिक जानने के लिए, एमडीएन दस्तावेज़ीकरण देखें ।


this सही कैसे देखें

इसका प्रयोग न करें

आप वास्तव में this विशेष रूप से उपयोग नहीं करना चाहते हैं, लेकिन ऑब्जेक्ट यह संदर्भित करता है । यही कारण है कि एक आसान समाधान केवल एक नया चर बनाने के लिए है जो उस वस्तु को भी संदर्भित करता है। चर में कोई नाम हो सकता है, लेकिन आम लोगों को self और that

 function MyConstructor(data, transport) { this.data = data; var self = this; transport.on('data', function() { alert(self.data); }); } 

चूंकि self एक सामान्य चर है, इसलिए यह शाब्दिक क्षेत्र नियमों का पालन करता है और कॉलबैक के अंदर पहुंच योग्य है। इसका भी फायदा यह है कि आप कॉलबैक के this मूल्य को खुद तक पहुंच सकते हैं।

स्पष्ट रूप से कॉलबैक के this सेट – भाग 1

ऐसा लग सकता है कि आपके पास इसके मूल्य पर कोई नियंत्रण नहीं है, क्योंकि इसका मान स्वचालित रूप से सेट है, लेकिन यह वास्तव में मामला नहीं है।

प्रत्येक फ़ंक्शन में विधि होती है। .bind [डॉक्स] , जो एक नया फ़ंक्शन देता है जिसके साथ एक मान को बाध्य किया जाता है। फ़ंक्शन में वही व्यवहार होता है, जिसे आपने बुलाया था। .bind पर, केवल यह कि आपके द्वारा सेट किया गया था। कोई फर्क नहीं पड़ता कि यह फ़ंक्शन कैसे या कब कहा जाता है, this हमेशा पारित मूल्य का संदर्भ देगा।

 function MyConstructor(data, transport) { this.data = data; var boundFunction = (function() { // parenthesis are not necessary alert(this.data); // but might improve readability }).bind(this); // <- here we are calling `.bind()` transport.on('data', boundFunction); } 

इस मामले में, हम कॉलबैक को MyConstructor के मूल्य के लिए बाध्य कर रहे हैं।

नोट: जब jQuery के लिए बाइंडिंग प्रसंग, तो इसके बजाय jQuery.proxy [docs] का उपयोग करें। ऐसा करने का कारण यह है कि किसी ईवेंट कॉलबैक को अटूट करने पर आपको फ़ंक्शन के संदर्भ को संग्रहीत करने की आवश्यकता नहीं है। jQuery आंतरिक रूप से संभालता है

ECMAScript 6: तीर कार्य का उपयोग करें

ECMASCrpt 6 तीर कार्यों का परिचय देता है , जिसे लैम्ब्डा फ़ंक्शंस के रूप में माना जा सकता है। उनके पास this बाध्यकारी नहीं है। इसके बजाय, this एक सामान्य चर की तरह गुंजाइश में देखा जाता है। इसका मतलब है कि आपको कॉल करने की ज़रूरत नहीं है। यह केवल एक विशेष व्यवहार नहीं है, कृपया अधिक जानकारी के लिए एमडीएन दस्तावेज देखें।

 function MyConstructor(data, transport) { this.data = data; transport.on('data', () => alert(this.data)); } 

कॉलबैक का this सेट this – भाग 2

कॉलबैक को स्वीकार करने वाले कुछ फ़ंक्शन / तरीके भी उस मूल्य को स्वीकार करते हैं जिसके कॉलबैक का this उल्लेख होना चाहिए। यह मूल रूप से यह स्वयं को बाध्य करने के समान है, लेकिन फ़ंक्शन / पद्धति आपके लिए यह है Array#map [डॉक्स] ऐसी विधि है इसका हस्ताक्षर है:

 array.map(callback[, thisArg]) 

पहला तर्क कॉलबैक है और दूसरा तर्क this दर्शाता है कि मूल्य क्या है। यहां एक अनुवाचित उदाहरण है:

 var arr = [1, 2, 3]; var obj = {multiplier: 42}; var new_arr = arr.map(function(v) { return v * this.multiplier; }, obj); // <- here we are passing `obj` as second argument 

नोट: आप this लिए एक मान पास कर सकते हैं या नहीं, उस समारोह / विधि के दस्तावेज़ीकरण में आमतौर पर उल्लेख किया गया है। उदाहरण के लिए, jQuery के $.ajax विधि [डॉक्स] context एक विकल्प का वर्णन करता context :

इस ऑब्जेक्ट को सभी अजाक्स से संबंधित कॉलबैक का संदर्भ दिया जाएगा।


सामान्य समस्या: कॉलबैक / ईवेंट हैंडलर के रूप में ऑब्जेक्ट विधियों का उपयोग करना

इस समस्या का एक अन्य आम अभिव्यक्ति है जब एक ऑब्जेक्ट विधि को कॉलबैक / ईवेंट हैंडलर के रूप में उपयोग किया जाता है फ़ंक्शंस जावास्क्रिप्ट में प्रथम श्रेणी के नागरिक हैं और शब्द "विधि" केवल एक समारोह के लिए एक संवादात्मक शब्द है जो ऑब्जेक्ट प्रॉपर्टी का मूल्य है लेकिन उस समारोह में "युक्त" ऑब्जेक्ट के लिए एक विशिष्ट लिंक नहीं है

निम्नलिखित उदाहरण पर विचार करें:

 function Foo() { this.data = 42, document.body.onclick = this.method; } Foo.prototype.method = function() { console.log(this.data); }; 

इस समारोह को क्लिक ईवेंट हैंडलर के रूप में असाइन किया गया है, लेकिन यदि शरीर क्लिक किया जाता है, तो मान का this.method undefined होगा, क्योंकि ईवेंट हैंडलर के अंदर, this शरीर को संदर्भित करता है, Foo का उदाहरण नहीं।
जैसा कि पहले से ही शुरूआत में उल्लेख किया गया है, इसका अर्थ this कि फ़ंक्शन को कैसे कहा जाता है , इस पर निर्भर करता है कि यह कैसे परिभाषित नहीं किया गया है
अगर कोड निम्न की तरह था, तो यह अधिक स्पष्ट हो सकता है कि फ़ंक्शन के ऑब्जेक्ट का कोई अंतर्निहित संदर्भ नहीं है:

 function method() { console.log(this.data); } function Foo() { this.data = 42, document.body.onclick = this.method; } Foo.prototype.method = method; 

इसका समाधान उपर्युक्त जैसा जैसा है: यदि उपलब्ध है, तो उपयोग this इसे किसी विशिष्ट मान के साथ स्पष्ट रूप से बाँध लें

 document.body.onclick = this.method.bind(this); 

या स्पष्ट रूप से समारोह को वस्तु के "विधि" के रूप में कॉल करते हैं, एक अनाम फ़ंक्शन का उपयोग करके कॉलबैक / ईवेंट हैंडलर होता है और ऑब्जेक्ट को एक अन्य चर में असाइन करता है:

 var self = this; document.body.onclick = function() { self.method(); }; 

या एक तीर फ़ंक्शन का उपयोग करें:

 document.body.onclick = () => this.method(); 

बाल संदर्भ के अंदर अभिभावक संदर्भ को एक्सेस करने के कई तरीके यहां हैं –

  1. आप bind() फ़ंक्शन का उपयोग कर सकते हैं – https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
  2. संदर्भ के संदर्भ में स्टोर करें / यह एक और चर के अंदर है
  3. ES6 एरो फ़ंक्शंस का उपयोग करें – https://derickbailey.com/2015/09/28/do-es6-arrow-functions-really-solve-this-in-javascript/
  4. कोड / फ़ंक्शन आर्किटेक्चर बदलें – इसके लिए आपको जावास्क्रिप्ट में डिजाइन पैटर्न पर कमांड होना चाहिए – https://addyosmani.com/resources/essentialjsdesignpatterns/book/

1. bind() फ़ंक्शन का उपयोग करें

 function MyConstructor(data, transport) { this.data = data; transport.on('data', ( function () { alert(this.data); }).bind(this) ); } // Mock transport object var transport = { on: function(event, callback) { setTimeout(callback, 1000); } }; // called as var obj = new MyConstructor('foo', transport); 

यदि आप underscore.jshttp://underscorejs.org/#bind उपयोग कर रहे हैं

 transport.on('data', _.bind(function () { alert(this.data); }, this)); 

2 संदर्भ के संदर्भ में स्टोर करें / यह एक और चर के अंदर है

 function MyConstructor(data, transport) { var self = this; this.data = data; transport.on('data', function() { alert(self.data); }); } 

3 तीर फ़ंक्शन

 function MyConstructor(data, transport) { this.data = data; transport.on('data', () => { alert(this.data); }); } 

यह एक विधि कॉल करने के "जादू" वाक्यविन्यास में है:

 object.property(); 

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

 var f = object.property; f(); 

जब आप किसी पद्धति का संदर्भ प्राप्त करते हैं, तो वह ऑब्जेक्ट से जुड़ा नहीं होता, यह केवल एक सादे फ़ंक्शन के संदर्भ होता है। ऐसा ही होता है जब आप कॉलबैक के रूप में संदर्भ का उपयोग करते हैं:

 this.saveNextLevelData(this.setAll); 

यही वह जगह है जहां आप फ़ंक्शन में संदर्भ बाँध लेंगे:

 this.saveNextLevelData(this.setAll.bind(this)); 

यदि आप jQuery का प्रयोग कर रहे हैं तो आपको इसके बजाय $.proxy विधि का उपयोग करना चाहिए, क्योंकि bind सभी ब्राउज़रों में समर्थित नहीं है:

 this.saveNextLevelData($.proxy(this.setAll, this)); 

"संदर्भ" के साथ समस्या

शब्द "संदर्भ" कभी-कभी इस संदर्भ से संदर्भित वस्तु को संदर्भित करने के लिए प्रयोग किया जाता है। इसका उपयोग अनुचित है क्योंकि यह ईसीएमएस्क्रिप्ट के साथ या तो शब्दात्मक या तकनीकी रूप से फिट नहीं है।

"संदर्भ" का अर्थ है कुछ ऐसी चीजें जो कि अर्थ को जोड़ती है, या कुछ पूर्ववर्ती और निम्न जानकारी जो अतिरिक्त अर्थ देती है। शब्द "प्रसंग" का उपयोग एक्जिक्यूशन संदर्भ को संदर्भित करने के लिए ECMAScript में किया जाता है, जो सभी पैरामीटर, क्षेत्र और कुछ निष्पादन कोड के दायरे में है।

यह ECMA-262 खंड 10.4.2 में दिखाया गया है:

कॉलिंग निष्पादन प्रसंग के ThisBinding के रूप में एक ही मूल्य के लिए यह बंधन सेट

जो स्पष्ट रूप से इंगित करता है कि यह एक निष्पादन संदर्भ का हिस्सा है।

एक निष्पादन संदर्भ आसपास की जानकारी प्रदान करता है जो निष्पादित किया जा रहा कोड के लिए अर्थ जोड़ता है। इसमें बहुत अधिक जानकारी शामिल है जो कि केवल बाइडिंग है

इसलिए इस का मान "संदर्भ" नहीं है, यह निष्पादन संदर्भ का सिर्फ एक हिस्सा है। यह अनिवार्य रूप से एक स्थानीय वैरिएबल है जिसे किसी ऑब्जेक्ट और सख्त मोड में किसी भी मूल्य के लिए कॉल द्वारा सेट किया जा सकता है।

पहले आपको "गुंजाइश" के संदर्भ में "इस" कीवर्ड के "गुंजाइश" और व्यवहार का स्पष्ट समझ होना चाहिए।

"यह" और "गुंजाइश":


 there are two types of scope in javascript. They are : 1) Global Scope 2) Function Scope 

संक्षेप में, वैश्विक दायरे से विंडो ऑब्जेक्ट को संदर्भित किया जाता है। वैश्विक संदर्भ में घोषित वेरिअबल्स कहीं से भी सुलभ हैं। दूसरे फ़ंक्शन पर एक फ़ंक्शन फ़ंक्शन के भीतर रहता है। किसी फ़ंक्शन के अंदर घोषित किए जाने वाले भक्त सामान्य रूप से बाहर की दुनिया से एक्सेस नहीं किए जा सकते हैं। वैश्विक दायरे में "यह" कीवर्ड विंडो वस्तु को दर्शाता है "यह" फ़ंक्शन के अंदर भी विंडो ऑब्जेक्ट को संदर्भित करता है। इसलिए "यह" विंडो को हमेशा संदर्भित करेगा जब तक कि हम अपनी पसंद के संदर्भ को इंगित करने के लिए "यह" हेरफेर करने का कोई तरीका ढूंढते हैं।

 -------------------------------------------------------------------------------- - - - Global Scope - - ( globally "this" refers to window object) - - - - function outer_function(callback){ - - - - // outer function scope - - // inside outer function"this" keyword refers to window object - - - callback() // "this" inside callback also refers window object - - } - - - - function callback_function(){ - - - - // function to be passed as callback - - - - // here "THIS" refers to window object also - - - - } - - - - outer_function(callback_function) - - // invoke with callback - -------------------------------------------------------------------------------- 

उदाहरण के साथ इस कॉलबैक में हेरफेर करने के विभिन्न तरीके:

यहां मेरे पास व्यक्ति नामक एक कंस्ट्रक्टर फ़ंक्शन है इसमें "name" नामक एक संपत्ति है और चार विधि "sayNameVersion1" , "sayNameVersion2" , "sayNameVersion3" , "sayNameVersion4" । उनमें से चारों के पास एक विशिष्ट कार्य है। कॉलबैक स्वीकार करें और इसे खोलें। कॉलबैक का एक विशिष्ट कार्य है जो व्यक्ति कंस्ट्रक्टर फ़ंक्शन के उदाहरण के नाम का लॉग इन करना है।

 function Person(name){ this.name = name this.sayNameVersion1 = function(callback){ callback.bind(this)() } this.sayNameVersion2 = function(callback){ callback() } this.sayNameVersion3 = function(callback){ callback.call(this) } this.sayNameVersion4 = function(callback){ callback.apply(this) } } function niceCallback(){ // function to be used as callback var parentObject = this console.log(parentObject) } 

अब व्यक्ति कंस्ट्रक्टर से एक उदाहरण बना सकते हैं और "sayNameVersionX" साथ "sayNameVersionX" विधि के विभिन्न संस्करणों को "sayNameVersionX" लिए देखते हैं कि हम व्यक्ति के उदाहरण को संदर्भित करने के लिए "यह" कॉलबैक के अंदर कितनी तरफ हेरफेर कर सकते हैं।

 var p1 = new Person('zami') // create an instance of Person constructor 

बाइंड करें:

क्या बाइंड करना है प्रदान किए गए मान पर सेट "this" कीवर्ड के साथ एक नया फ़ंक्शन बनाना।

sayNameVersion1 और sayNameVersion2 कॉलबैक फ़ंक्शन के "यह" हेरफेर करने के लिए बाइंड का उपयोग करें।

 this.sayNameVersion1 = function(callback){ callback.bind(this)() } this.sayNameVersion2 = function(callback){ callback() } 

पहले एक "बाइ" इस विधि के भीतर कॉलबैक के साथ। और दूसरा कॉलबैक ऑब्जेक्ट से जुड़ा हुआ है।

 p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback 

कॉल करें:

"कॉल" पद्धति का पहला तर्क उस फ़ंक्शन के अंदर प्रयोग किया जाता है जिसे इसे "कॉल" से जुड़ा हुआ है।

sayNameVersion3 विंडो ऑब्जेक्ट के बजाय हमने बनाई गई उस व्यक्ति ऑब्जेक्ट को संदर्भित करने के लिए "यह" हेरफेर करने के लिए कॉल का उपयोग करता है

 this.sayNameVersion3 = function(callback){ callback.call(this) } 

और इसे निम्नलिखित की तरह कहा जाता है:

 p1.sayNameVersion3(niceCallback) 

लागू करें :

"कॉल" के समान, लागू करने का पहला तर्क उस ऑब्जेक्ट को संदर्भित करता है जिसे "this" कीवर्ड द्वारा इंगित किया जाएगा।

sayNameVersion4 व्यक्ति वस्तु को संदर्भित करने के लिए "यह" हेरफेर करने के लिए उपयोग करता है

 this.sayNameVersion4 = function(callback){ callback.apply(this) } 

और इसे निम्नलिखित की तरह कहा जाता है। बस कॉलबैक पारित किया जाता है,

 p1.sayNameVersion4(niceCallback) 

हम इसे टाइमआउट () सेट करने के लिए बाध्य नहीं कर सकते, क्योंकि यह हमेशा वैश्विक ऑब्जेक्ट (विंडो) के साथ निष्पादित होता है, यदि आप कॉलबैक फ़ंक्शन में "इस" संदर्भ को एक्सेस करना चाहते हैं, तो कॉलबैक फ़ंक्शन को बाइंड () का उपयोग करके हम इसे प्राप्त कर सकते हैं:

 setTimeout(function(){ this.methodName(); }.bind(this), 2000);