जावास्क्रिप्ट "यह" सूचक नेस्टेड फ़ंक्शन के भीतर


94

मेरे पास एक प्रश्न है कि "यह" पॉइंटर को नेस्टेड फ़ंक्शन परिदृश्य में कैसे व्यवहार किया जाता है।

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

किसी भी संकेत (कोई उद्देश्य नहीं) की सराहना की जाएगी।

var std_obj = {
  options : { rows: 0, cols: 0 },
  activeEffect : "none",
  displayMe : function() {

    // the 'this' pointer is referring to the std_obj
    if (this.activeEffect=="fade") { }

    var doSomeEffects = function() {

      // the 'this' pointer is referring to the window obj, why?
      if (this.activeEffect=="fade") { }

    }

    doSomeEffects();   
  }
};

std_obj.displayMe();

आपका सवाल क्या है?
सरफराज

2
जब किसी फ़ंक्शन के अंदर उपयोग किया जाता है, तो thisउस ऑब्जेक्ट को संदर्भित करता है जिस पर फ़ंक्शन को लागू किया जाता है।
लगभग

8
बाहरी दायरे में आप जो कर सकते हैं वह कुछ ऐसा है var self = this;और फिर selfबंद के माध्यम से आंतरिक कार्य को देखें ।
काई

1
doSomeEffectsविशेष रूप से किसी भी obj से जुड़ा नहीं है, इसलिए thisइसे सभी तत्वों की मां, खिड़की माना जाता है।
लगभग

3
@JoJoeDad मैं कूटनीतिक रूप से यह कैसे कहूं? लेकिन नीचे chuckj द्वारा दिया गया उत्तर आपके प्रश्न का उत्तर है। वास्तव में यह समझने के लिए कि क्या चल रहा है, आपको निष्पादन संदर्भ , गुंजाइश श्रृंखला और इस कीवर्ड को पढ़ना चाहिए । और यहाँ कुछ उत्तरों की शक्ल से, अन्य लोगों को उन्हें भी पढ़ना चाहिए। मैं अच्छी जावास्क्रिप्ट को प्रचारित करने की कोशिश करता हूं। यही कारण है कि मैं इन लिंक को देने के लिए समय ले रहा हूं।
वनफुटस्विल

जवाबों:


120

जावास्क्रिप्ट में thisवस्तु वास्तव में इस बात पर आधारित है कि आप अपने फ़ंक्शन को कैसे बनाते हैं।

सामान्य तौर पर thisऑब्जेक्ट को सेटअप करने के तीन तरीके हैं :

  1. someThing.someFunction(arg1, arg2, argN)
  2. someFunction.call(someThing, arg1, arg2, argN)
  3. someFunction.apply(someThing, [arg1, arg2, argN])

उपरोक्त सभी उदाहरणों में thisवस्तु होगी someThing। एक प्रमुख अभिभावक वस्तु के बिना किसी फ़ंक्शन को कॉल करने से आमतौर पर आपको वैश्विक ऑब्जेक्ट मिलेगा जो कि अधिकांश ब्राउज़र में windowऑब्जेक्ट का मतलब है ।


मैंने this.doSomeEffects();आपके उत्तर के आधार पर कोड बदल दिया है लेकिन फिर भी यह काम नहीं करता है। क्यों?
अरशसॉफ्ट

1
@Arashsoft thisको this.doSomeEffects()अंकों में std_obj। जैसा कि ऊपर दिए गए जवाब में बताया गया है कि यदि किसी फंक्शन में ऑब्जेक्ट रेफरेंस नहीं है, तो thisविंडो ऑब्जेक्ट होने में समय लगता है।
शिवम

38

चूँकि यह अपनी तरह के सबसे अधिक पूछे जाने वाले सवालों में से एक है, इसलिए मुझे इन सभी वर्षों के बाद, ES6 समाधान को तीर के साथ जोड़ दें:

var std_obj = {
  ...
  displayMe() {
    ...
    var doSomeEffects = () => {
                        ^^^^^^^    ARROW FUNCTION    
      // In an arrow function, the 'this' pointer is interpreted lexically,
      // so it will refer to the object as desired.
      if (this.activeEffect=="fade") { }
    };
    ...    
  }
};

5
अब यह प्रगति है!
जोशुआ पिंटर

उत्कृष्ट, सरल, समाधान।
जोशुआ श्लिक्टिंग

32

thisक्लोजर स्कोप का हिस्सा नहीं है, इसे कॉल साइट पर बाध्य फ़ंक्शन के लिए एक अतिरिक्त पैरामीटर के रूप में सोचा जा सकता है। यदि विधि को विधि के रूप में नहीं कहा जाता है, तो वैश्विक वस्तु के रूप में पारित किया जाता है this। ब्राउज़र में, वैश्विक ऑब्जेक्ट समान है window। उदाहरण के लिए, निम्नलिखित कवक पर विचार करें,

function someFunction() {
}

और निम्न वस्तु,

var obj = { someFunction: someFunction };

यदि आप विधि सिंटैक्स का उपयोग करके फ़ंक्शन को कॉल करते हैं, जैसे,

obj.someFunciton();

तब के thisलिए बाध्य है obj

यदि आप कुछ कॉल करते हैं () सीधे, जैसे,

someFunction();

तब thisवैश्विक वस्तु के लिए बाध्य है, वह है window

चारों ओर सबसे आम काम यह है कि इसे बंद करने के लिए कब्जा कर लिया जाए जैसे,

displayMe : function() {      

    // the 'this' pointer is referring to the std_obj      
    if (this.activeEffect=="fade") { }      
    var that = this;  
    var doSomeEffects = function() {      

      // the 'this' pointer is referring to global
      // that, however, refers to the outscope this
      if (that.activeEffect=="fade") { }      
    }      

    doSomeEffects();         
 }      

वह = यह एकदम सही है
नाथ वेबर

10

संलग्नक चर और "यह" के बीच अंतर है। "यह" वास्तव में फ़ंक्शन के इनोकर द्वारा परिभाषित किया गया है, जबकि स्पष्ट चर बाड़े के रूप में ज्ञात फ़ंक्शन घोषणा ब्लॉक के अंदर बरकरार हैं। नीचे दिए गए उदाहरण देखें:

function myFirstObject(){
    var _this = this;
    this.name = "myFirstObject";
    this.getName = function(){
       console.log("_this.name = " + _this.name + " this.name = " + this.name);  
    }
}

function mySecondObject(){
    var _this = this;
    this.name = "mySecondObject";
    var firstObject = new myFirstObject();
    this.getName = firstObject.getName
}

var secondObject = new mySecondObject();
secondObject.getName();

आप इसे यहाँ आज़मा सकते हैं: http://jsfiddle.net/kSTBy/

आपके फ़ंक्शन में क्या हो रहा है "doSomeEffects ()", स्पष्ट रूप से कहा जा रहा है, इसका अर्थ है संदर्भ या फ़ंक्शन का "यह" विंडो है। अगर "doSomeEffects" एक प्रोटोटाइप तरीका था, जैसे "myObject" पर इस .doSomeEffects, तो myObject.doSomeEffects () "my" के "myObject" होने का कारण होगा।


4
आलसी और अधीर के लिए, यह डेमो लॉग करता है:_this.name = myFirstObject this.name = mySecondObject
ptim

9

इस प्रश्न को समझने के लिए, निम्नलिखित स्निपेट के लिए आउटपुट प्राप्त करने का प्रयास करें

var myObject = {
    foo: "bar",
    func: function() {
        var self = this;
        console.log("outer func:  this.foo = " + this.foo);
        console.log("outer func:  self.foo = " + self.foo);
        (function() {
            console.log("inner func:  this.foo = " + this.foo);
            console.log("inner func:  self.foo = " + self.foo);
        }());
    }
};
myObject.func();

उपरोक्त कोड कंसोल को निम्न आउटपुट देगा:

outer func:  this.foo = bar
outer func:  self.foo = bar
inner func:  this.foo = undefined
inner func:  self.foo = bar

बाहरी कार्य में, यह और स्व दोनों myObject को संदर्भित करते हैं और इसलिए दोनों ठीक से संदर्भ और अभिगम का उपयोग कर सकते हैं।

हालाँकि, आंतरिक फ़ंक्शन में, यह अब myObject को संदर्भित नहीं करता है। नतीजतन, यह .foo आंतरिक फ़ंक्शन में अपरिभाषित है, जबकि स्थानीय चर स्व का संदर्भ गुंजाइश में रहता है और वहां पहुंच योग्य है। (ECMA 5 से पहले, यह आंतरिक फ़ंक्शन वैश्विक विंडो ऑब्जेक्ट को संदर्भित करेगा; जबकि ECMA 5 के रूप में, आंतरिक फ़ंक्शन में यह अपरिभाषित होगा।)


1
आंतरिक फ़ंक्शन में, thisविंडो ऑब्जेक्ट (ब्राउज़र वातावरण में) या GLOBAL ऑब्जेक्ट (एक नोड में) पर्यावरण को संदर्भित करता है
raneshu

2
ऐसा क्यों होता है?
सेतु

@raneshu "सख्त का उपयोग करें" और thisअब खिड़की को संदर्भित नहीं करता है
रॉफ्रोल

3

जैसा कि काइल द्वारा समझाया गया है, आप उपयोग कर सकते हैं callया फ़ंक्शन के भीतर applyनिर्दिष्ट कर सकते हैं this:

यह वह अवधारणा है जो आपके कोड पर लागू होती है:

var std_obj = {
    options: {
        rows: 0,
        cols: 0
    },
    activeEffect: "none",
    displayMe: function() {

        // the 'this' pointer is referring to the std_obj
        if (this.activeEffect == "fade") {}

        var doSomeEffects = function() {
            // the 'this' pointer is referring to the window obj, why?
            if (this.activeEffect == "fade") {}
        }

        doSomeEffects.apply(this,[]);
    }
};

std_obj.displayMe();

JsFiddle


0

मुझे एक चेतावनी मिली " इस माध्यम से एक वर्ग के क्षेत्र में संभावित रूप से अमान्य संदर्भ पहुंच "

class MyListItem {
    constructor(labelPrm) {
        this._flagActive = false;
        this._myLabel = labelPrm;
        labelPrm.addEventListener('click', ()=>{ this.onDropdownListsElementClick();}, false);
    }

    get myLabel() {
        return this._myLabel
    }
    get flagActive(){
        return this._flagActive;
    }

    onDropdownListsElementClick(){console.log("Now'this'refers to the MyListItem itself")}}//end of the class

0

चूंकि इसका उल्लेख नहीं किया गया था, इसलिए मैं उल्लेख करूंगा कि उपयोग .bind()करना एक समाधान है -


        doSomeEffects=doSomeEffect.bind(this);
        doSomeEffects();   
      }
    };

    std_obj.displayMe();

यहाँ एक और अधिक सरल उदाहरण है -

bad = { 
  name:'NAME', 
  z : function() { 
    function x() { console.log(this.name); }; 
    x() 
  } 
};
bad.z() // prints 'undefined'

good = { 
  name:'NAME', 
  z : function() { 
    function x() { console.log(this.name); }; 
    x=x.bind(this);
    x();
  } 
};
good.z() // prints 'NAME'

यह सही है कि एरो फंक्शन =>का उपयोग करने से स्लीकर दिखता है और प्रोग्रामर के लिए आसान है। हालांकि, यह ध्यान में रखा जाना चाहिए कि एक लेक्सिकल स्कोप को प्रोसेसिंग और मेमोरी की स्थापना के लिए अधिक काम की आवश्यकता होती है और उस लेक्सिकल स्कोप को बनाए रखने की तुलना में, किसी फ़ंक्शन thisको एक पॉइंटर के साथ जोड़ने की तुलना में .bind()

जेएस में विकासशील वर्गों के लाभ का एक हिस्सा thisकार्यात्मक प्रोग्रामिंग और लेक्सिकल स्कोप्स से दूर रखने के लिए और इस तरह ओवरहेड को कम करने के लिए अधिक मज़बूती से मौजूद और उपलब्ध कराने के लिए एक विधि प्रदान करना था ।

एमडीएन से

प्रदर्शन के विचार यह अनावश्यक रूप से अन्य कार्यों के भीतर कार्य बनाने के लिए नासमझ है अगर किसी विशेष कार्य के लिए क्लोजर की आवश्यकता नहीं है, क्योंकि यह प्रसंस्करण गति और मेमोरी खपत दोनों के मामले में स्क्रिप्ट के प्रदर्शन को नकारात्मक रूप से प्रभावित करेगा।

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