क्या इस जावास्क्रिप्ट मुहावरे को रेखांकित करता है: var self = this?


357

मैंने WebKit HTML 5 SQL स्टोरेज नोट्स डेमो के लिए स्रोत में निम्नलिखित को देखा :

function Note() {
  var self = this;

  var note = document.createElement('div');
  note.className = 'note';
  note.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
  note.addEventListener('click', function() { return self.onNoteClick() }, false);
  this.note = note;
  // ...
}

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


4
यह एक जेएस भाषा की सुविधा है जिसे "लेक्सिकल क्लोजर" कहा जाता है
12

2
की संभावित डुप्लिकेट: var self = this?
डेविड आरआर

THIS की अवधारणा को यहाँ स्पष्ट रूप से समझाया गया है scotch.io/@alZami/understanding-this-in-javascript
AL-zami

इस उत्तर में प्रासंगिक उदाहरण stackoverflow.com/a/20279485/5610569 (प्रश्न " thisकॉलबैक के अंदर सही कैसे पहुंचें ?")
FluxLemur

जवाबों:


431

इस लेख को देखें alistapart.com पर । (एड: लेख मूल रूप से जुड़े होने के बाद से अपडेट किया गया है)

selfthisसंदर्भ को बदलने के लिए भी मूल के संदर्भ को बनाए रखने के लिए उपयोग किया जा रहा है। यह अक्सर इवेंट हैंडलर (विशेषकर क्लोजर में) में उपयोग की जाने वाली तकनीक है।

संपादित करें: ध्यान दें कि selfअब उपयोग करना window.selfमौजूद है क्योंकि आप सावधान नहीं हैं और त्रुटियों का कारण बन सकते हैं।

जिसे आप वैरिएबल कहते हैं वह विशेष रूप से महत्वपूर्ण नहीं है। var that = this;ठीक है, लेकिन नाम के बारे में कुछ भी जादू नहीं है।

एक संदर्भ (जैसे कॉलबैक, क्लोजर) के अंदर घोषित किए गए कार्यों में एक ही दायरे या ऊपर घोषित चर / फ़ंक्शन तक पहुंच होगी।

उदाहरण के लिए, एक साधारण ईवेंट कॉलबैक:

function MyConstructor(options) {
  let that = this;

  this.someprop = options.someprop || 'defaultprop';

  document.addEventListener('click', (event) => {
    alert(that.someprop);
  });
}

new MyConstructor({
  someprop: "Hello World"
});


उस लेख का उपयोग करते हुए प्रकट होता हैvar that = this;
बॉब स्टीन

@ डबस्टाइन धन्यवाद। मैं उसी हिसाब से जवाब अपडेट करूंगा।
जोनाथन फिंगलैंड

96

मुझे लगता है कि चर नाम का 'स्व' अब इस तरह से उपयोग नहीं किया जाना चाहिए, क्योंकि आधुनिक ब्राउज़र एक वैश्विक चर प्रदान करते हैंself एक सामान्य या तो एक सामान्य विंडो या एक वेबवर्क की ओर इशारा करते हुए करते हैं।

भ्रम और संभावित संघर्षों से बचने के लिए, आप लिख सकते हैं var thiz = thisया var that = thisइसके बजाय।


43
मैं आमतौर पर उपयोग करें_this
djheru

6
@djheru +1। " that" की तुलना में इतना अच्छा (जो मेरे दिमाग को कभी आदत नहीं होगी)।
o_o_o--

9
मैंने "मी" :) का उपयोग करना शुरू कर दिया
मपपार्थी रवींद्रनाथ

3
जब तक आधुनिक ब्राउज़र एक वैश्विक चर _this, या मुझे प्रदान करना शुरू नहीं करते हैं।
बीजोर

10
जब selfतक आप इसे varआईबॉल घोषित करते हैं, तब तक नाम का उपयोग करने में कोई समस्या नहीं है , यह वैश्विक स्तर पर छाया रहेगा। बेशक अगर आप भूल गए varतो यह किसी अन्य नाम के साथ भी काम नहीं करेगा।
बरगी

34

हाँ, आप इसे हर जगह देखेंगे। यह अक्सर होता हैthat = this;

देखें कि selfघटनाओं द्वारा अंदर के कार्यों का उपयोग कैसे किया जाता है? उन का अपना संदर्भ होगा, इसलिए selfइसका प्रयोग किया जाता है जो thisकि पकड़ में आयाNote()

कारण selfअभी भी फ़ंक्शन के लिए उपलब्ध है, भले ही वे केवल Note()फ़ंक्शन को निष्पादित करने के बाद निष्पादित कर सकते हैं , यह है कि आंतरिक फ़ंक्शन को बंद होने के कारण बाहरी फ़ंक्शन का संदर्भ मिलता है ।


12
मेरे लिए संयोग बिंदु का selfकोई विशेष अर्थ नहीं है। मैं व्यक्तिगत रूप से किसी अन्य नाम के एक संस्करण का उपयोग करना पसंद करता हूं selfक्योंकि यह अक्सर मुझे भ्रमित करता है, क्योंकि मैं एक आरक्षित शब्द होने की अपेक्षा करता हूं। तो मुझे आपका जवाब पसंद है। और ओपी के उदाहरण में, मैं पसंद करूंगा var thisNote = thisया समान।
स्टीव

@steve ने सहमति व्यक्त की, हालांकि मैं सामान्य रूप से इस / आत्म संदर्भों का उपयोग करने से बचने की कोशिश करता हूं क्योंकि वे स्थिरता के मामले में बहुत भंगुर हैं।
मैटलुमस

28

यह भी ध्यान दिया जाना चाहिए कि thisयदि आप नापसंद करते हैं तो कॉलबैक में मूल के संदर्भ को बनाए रखने के लिए एक वैकल्पिक प्रॉक्सी पैटर्न हैvar self = this मुहावरा ।

किसी फ़ंक्शन को दिए गए संदर्भ के साथ उपयोग करके बुलाया जा सकता है function.applyया function.call, आप एक रैपर लिख सकते हैं जो एक फ़ंक्शन देता है जो दिए गए संदर्भ के साथ applyया callउपयोग करके आपके फ़ंक्शन को कॉल करता है। proxyइस पैटर्न के कार्यान्वयन के लिए jQuery का कार्य देखें । यहाँ इसका उपयोग करने का एक उदाहरण है:

var wrappedFunc = $.proxy(this.myFunc, this);

wrappedFuncतब बुलाया जा सकता है और आपके पास thisसंदर्भ के रूप में आपका संस्करण होगा ।


10

जैसा कि दूसरों ने समझाया है, var self = this;एक बंद में कोड की अनुमति देता है माता-पिता के दायरे में वापस आने के लिए करने की ।

हालाँकि, यह अब 2018 है और ES6 व्यापक रूप से सभी प्रमुख वेब ब्राउज़रों द्वारा समर्थित है। var self = this;मुहावरा काफी के रूप में आवश्यक के रूप में यह एक बार नहीं है।

तीर के कार्योंvar self = this; के उपयोग से बचना अब संभव है ।

ऐसे उदाहरणों में जहां हमने प्रयोग किया होगा var self = this:

function test() {
    var self = this;
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", function() {
        console.log(self.hello); // logs "world"
    });
};

अब हम बिना एरो फंक्शन का उपयोग कर सकते हैं var self = this:

function test() {
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", () => {
        console.log(this.hello); // logs "world"
    });
};

एरो फ़ंक्शंस के पास अपना नहीं होता है thisऔर बस एनक्लोज़िंग स्कोप होता है।


या - झटका, डरावना! - अपने फ़ंक्शन (बंद करने) के तर्क के रूप में वास्तविक प्रासंगिक चीज़ को पास क्यों नहीं करें? क्यों नरक आप गुंजाइश राज्य से बाहर संदर्भित कर रहे हैं, क्यों नरक किसी को भी इस तरह की प्रोग्रामिंग है? ऐसा करने का कोई वास्तविक कारण कभी नहीं है । इसके बजाय .addEventListender("click", (x) => { console.log(x); });आपने समझाया है कि कैसे और क्यों बहुत स्पष्ट रूप से, और मैं मानता हूं कि तीर के कार्यों का उपयोग करना अधिक समझ में आता है, लेकिन फिर भी ... यह सिर्फ भयानक, आलसी, गड़बड़, प्रोग्रामिंग है।
बेंजामिन R

2
जावास्क्रिप्ट में, माता-पिता के दायरे का जिक्र करना बेहद सामान्य और आवश्यक है। यह भाषा का एक मूलभूत हिस्सा है। पैरेंट स्कोप में पास होने के लिए आपका सुझाव इवेंट हैंडलर पर एक तर्क के रूप में वास्तव में संभव नहीं है। इसके अलावा, ES6 में, तीर फ़ंक्शन लेक्सिकल स्कूपिंग का उपयोग करते हैं - 'यह' यह वर्तमान आसपास के दायरे को संदर्भित करता है और आगे नहीं - यह "स्कोप राज्य से बाहर संदर्भित" या ऐसा कुछ भी नहीं है।
इलियट बी।

9

चर को विधि में परिभाषित इनलाइन फ़ंक्शन द्वारा कैप्चर किया जाता है। thisफ़ंक्शन में किसी अन्य ऑब्जेक्ट को संदर्भित करेगा। इस तरह, आप फ़ंक्शन thisको बाहरी दायरे में संदर्भ रख सकते हैं ।


9

यह एक जावास्क्रिप्ट क्विक है। जब कोई कार्य किसी वस्तु का गुण होता है, तो अधिक उपयुक्त रूप से एक विधि कहा जाता है, यह वस्तु को संदर्भित करता है। ईवेंट हैंडलर के उदाहरण में, सम्‍मिलित ऑब्जेक्ट वह तत्व है जिसने ईवेंट को ट्रिगर किया है। जब एक मानक फ़ंक्शन लागू किया जाता है, तो यह वैश्विक ऑब्जेक्ट को संदर्भित करेगा। जब आपके पास अपने उदाहरण के रूप में नेस्टेड फ़ंक्शन होते हैं, तो यह बाहरी फ़ंक्शन के संदर्भ से बिल्कुल भी संबंधित नहीं है। इनर काम करता है, जिसमें समारोह के साथ साझा करें गुंजाइश ऐसा डेवलपर्स के रूपांतरों का उपयोग करेगा var that = thisक्रम में बनाए रखने के लिए यह वे भीतरी समारोह में की जरूरत है।


5

वास्तव में स्व विंडो के लिए एक संदर्भ है ( window.self) इसलिए जब आप कहते var self = 'something'हैं कि आप अपने आप में एक विंडो संदर्भ को ओवरराइड करते हैं - क्योंकि विंडो ऑब्जेक्ट में स्वयं मौजूद है।

यही कारण है कि ज्यादातर डेवलपर्स var that = thisओवर पसंद करते हैंvar self = this;

वैसे भी, var that = this;अच्छे अभ्यास के अनुरूप नहीं है ... यह मानते हुए कि आपके कोड को अन्य डेवलपर्स द्वारा बाद में संशोधित / संशोधित किया जाएगा जिसे आपको डेवलपर समुदाय के संबंध में सबसे सामान्य प्रोग्रामिंग मानकों का उपयोग करना चाहिए

इसलिए आपको अपने दायरे में स्पष्ट होने के लिए var oldThis/ var oThis/ etc - जैसे कुछ का उपयोग करना चाहिए। .. लेकिन यह उतना नहीं है लेकिन कुछ सेकंड और कुछ मस्तिष्क चक्रों को बचाएगा


2
@ मेरा मानना ​​है कि यह अंतिम पैराग्राफ तक समझ में आता है।
मिपेह

0

जैसा कि ऊपर कई बार उल्लेख किया गया है, 'स्व' का उपयोग केवल फंकशन में प्रवेश करने से पहले 'इस' का संदर्भ रखने के लिए किया जा रहा है। एक बार समारोह में 'यह' कुछ और को संदर्भित करता है।


@ जॉनपॉल ... यह एक उत्तर प्रदान करता है । यह सही उत्तर नहीं हो सकता है, लेकिन आप यह कैसे कह सकते हैं कि "इसका उपयोग किया जा रहा है ..." "उसने ऐसा क्यों किया" इसका जवाब नहीं है।
ग्रीनएजजादे

-1
function Person(firstname, lastname) {
  this.firstname = firstname;

  this.lastname = lastname;
  this.getfullname = function () {
    return `${this.firstname}   ${this.lastname}`;
  };

  let that = this;
  this.sayHi = function() {
    console.log(`i am this , ${this.firstname}`);
    console.log(`i am that , ${that.firstname}`);
  };
}

let thisss = new Person('thatbetty', 'thatzhao');

let thatt = {firstname: 'thisbetty', lastname: 'thiszhao'};

thisss.sayHi.call (thatt);


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