2009-02-12 5 views
8

मैं इसे एक भाषा डिजाइन बिंदु से पूछ रहा हूं। इसलिए मैंजावास्क्रिप्ट में 'इस' कीवर्ड के व्यवहार के लिए तर्क क्या है?

  1. this के व्यवहार के लिए तर्क क्या है?
  2. this का व्यवहार किस गिनती थी, या उस पर सुधार किया जा सकता था?

स्पष्ट करने के लिए कारण है कि मैं this को लेकर असहज कर रहा हूँ, पर विचार इस उदाहरण: f() हैं

var a = {}; 
a.f = function(){ return this; } 
var f = a.f; 
// f() != a.f() 

नोट कितनी आसानी से वस्तु जो करने के लिए खो दिया है: a से अलग कर दिया, this वैश्विक हो जाता है ऑब्जेक्ट (window ब्राउज़रों के लिए)।

अब विचार करें:

var newA = function(){ 
    var self = {}; 
    self.f = function(){ return self; } 
    return self; 
} 

var a = newA(); 
var f = a.f; 
// f() == a.f() ! 

बिल्कुल this का उपयोग कर के बिना, हम जहां या कैसे विधि का इस्तेमाल किया जाता है की परवाह किए बिना की स्थापना और वस्तु संदर्भ बनाए रखने में सक्षम हैं। मैं मदद नहीं कर सकते लेकिन लगता है कि, शक्ति है कि बंद प्रदान के साथ, this ज़रूरत से ज़्यादा, और शायद यह भी एक छोटे से खतरनाक हो जाता है ...

मैं कुछ बदले की भावना पर this के खिलाफ नहीं हूँ, या एक बहस शुरू करने के लिए देख; मैं बस इसे बेहतर समझने की कोशिश कर रहा हूं। मैं सराहना करता हूं कि 'यह' उपयोगी हो सकता है, लेकिन it can be confusing को भी पहचानें ... निश्चित रूप से शुरुआती लोगों के लिए भ्रमित, और शायद विशेषज्ञों के साथ-साथ पर्याप्त अस्पष्ट मामलों में भी।

और फिर भी, यह भाषा का भारी उपयोग और प्रतीत होता है, इस समय भाषा के अन्य मूल पहलुओं को चमकदार (यानी, क्रॉकफोर्ड और with या new) के लिए उचित खेल लगता है। मुझे तब क्या याद आ रहा है, जो this अनिवार्य बनाता है?

+0

आपको यह इंप्रेशन देता है कि "यह" एक गलती है? –

+0

@ गैमेकैट: आपने कभी जावास्क्रिप्ट के समान भाषा तैयार करने की कोशिश नहीं की है, है ना? – artificialidiot

+0

मुझे अभी भी लगता है कि यह तर्कवादी है। भाषा एक समस्या का तात्पर्य है, सीएफ "यह कितना अद्भुत है 'यह' (यदि यह अद्भुत है)" – annakata

उत्तर

11

आप के रूप में यह निश्चित OO भाषाओं में करता है, जहां यह हमेशा वस्तु एक विधि के अंतर्गत आता है को संदर्भित करता है इस तरह से व्यवहार करने की उम्मीद कर रहे हैं।

लेकिन जावास्क्रिप्ट में, फ़ंक्शन एकाधिक ऑब्जेक्ट्स, या कोई ऑब्जेक्ट से जुड़ा जा सकता है। आपके उदाहरण में, आपने के संदर्भ में एक विशिष्ट ऑब्जेक्ट के संदर्भ में उपयोग किए जाने वाले फ़ंक्शन को लिखा है ... लेकिन कुछ भी मुझे उस फ़ंक्शन को लेने और इसे किसी अन्य ऑब्जेक्ट से जोड़ने से रोकता है। यह सिर्फ भाषा की प्रकृति है - कार्य प्रथम श्रेणी हैं, ऑब्जेक्ट सदस्यता वैकल्पिक है।

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

3
  • यह
  • OO सामान के बहुत सारे नहीं था
  • यह जिस तरह से यह
+1

ठीक है। क्या आप ओओ सामानों के बारे में उदाहरण देने के बारे में सोचेंगे? –

+0

यह एक बहुत ही असहनीय उत्तर है, क्योंकि लेखक तर्क या उदाहरणों के समर्थन के बिना तथ्य के रूप में राय बता रहा है। -1 – rix0rrr

+0

माइक जी: सार्वजनिक कार्यों को बनाना rix0rr: तथ्यों के साथ वापस जाना मुश्किल है क्योंकि दूसरी तरफ – svinto

1
  • है यह 'स्वयं' के बजाय
  • कुछ भी बुलाया जाना चाहिए कि वर्तमान को संदर्भित करता है अच्छा है वस्तुओं की स्थिति।
  • 'इस' के नाम के रूप में 'स्वयं' चुनकर, और इसे सभी विधियों के लिए स्पष्ट रूप से (पहले तर्क के रूप में) पास करके। इस तरह आप स्थिर विधि या फ़ंक्शन से इंस्टेंस विधि को आसानी से बता सकते हैं।

क्षमा करें, लेकिन मैं वास्तव में अजगर ;-)

+0

के रूप में राय बता रहा था, मुझे लगता है कि इसे कॉल किया जाना चाहिए मुझे;) –

+0

वाह, किसी को हास्य की भावना नहीं है? 'इस' के लिए डाउनवॉटिंग? – Abgan

+0

आप यह उल्लेख करना भूल गए हैं कि आप 'स्वयं' को पूरी तरह से पहुंचने के बजाय किसी विधि के पहले तर्क के रूप में पारित करना चाहते हैं। –

3

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

अनबाउंड "इस" को हटाकर शायद चीजों को और अधिक कठिन नहीं बनायेगा।

संपादित करें: मुझे लगता है कि एक वैकल्पिक वाक्यविन्यास उदाहरण मेरा रुख स्पष्ट कर देगा।

function Foo() 
{ 
    //both this refer to the Foo instance 
    this.blah=this.function(){this.bar;}; 

    //second this refers to baz 
    this.blah=baz.function(){this.bar;}; 

    //second this refers to anonymous function itself 
    this.blah=function(){this.bar;}; 
} 
8

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

function Person(first, last, age) { 
    this.firstName = first; 
    this.lastName = last; 
    this.age = age; 
} 

Person.prototype.getFullName = function() { 
    return this.firstName + " " + this.lastName; 
}; 

"इस" एक व्यक्ति वस्तु का उल्लेख करने की जरूरत है, लेकिन समारोह Person.prototype.getName करने के लिए सौंपा जानते हुए भी यह कैसे उपयोग किया जा रहा है की किसी भी तरह से नहीं है, तो "इस" जिस वस्तु को बुलाया जाता है उसे बाध्य करने की आवश्यकता है।

जहां यह समस्या का कारण बनता है, तब होता है जब आपके पास घोंसले कार्य होते हैं।

// This is a really contrived example, but I can't think of anything better 
Person.prototype.getInfo = function() { 
    // get name as "Last, First" 
    function getNameLastFirst() { 
     // oops. "this" is the global object, *not* the Person 
     return this.lastName + ", " + this.firstName; 
    } 

    // expect something like "Crumley, Matthew: Age 25", 
    // but you get "undefined, undefined: Age 25" 
    return getNameLastFirst() + ": Age " + this.age; 
}; 

वाक्य रचना artificialidiot सुझाव सुविधाजनक होगा, लेकिन इसे लागू का उपयोग कर "इस" एक विशिष्ट वस्तु के लिए बाध्य करने के लिए बहुत आसान है:

function bind(func, obj) { 
    return function() { 
     return func.apply(obj, arguments); 
    }; 
} 

Person.prototype.getInfo = function() { 
    // get name as "Last, First" 
    var getNameLastFirst = bind(function() { 
     return this.lastName + ", " + this.firstName; 
    }, this); 

    return getNameLastFirst() + ": Age " + this.age; 
}; 

या अधिक "पारंपरिक" विधि बंद का उपयोग कर:

Person.prototype.getInfo = function() { 
    var self = this; 

    // get name as "Last, First" 
    function getNameLastFirst() { 
     return self.lastName + ", " + self.firstName; 
    } 

    return getNameLastFirst() + ": Age " + this.age; 
}; 
+0

मैथ्यू क्रूमली, (मुझे नहीं पता कि "@" चिह्न क्यों काम नहीं कर रहा है लेकिन उम्मीद है कि आप इस पोस्ट को देखेंगे)। मैं आपके उत्तर में अपने कोड का पालन करने की कोशिश कर रहा हूं, लेकिन शायद मुझे कुछ याद आ रही है? कृपया मुझे बताएं, आप 'getNameFirstLast' फ़ंक्शन कहां परिभाषित कर रहे हैं? क्या यह एक टाइपो है और क्यों यह वापसी मूल्य अनिर्धारित हैं? धन्यवाद। – Chris22

+0

@ क्रिस 22 ओप्स, वह एक टाइपो था। यह 'getNameLastFirst() 'होना चाहिए। पहले उदाहरण में यह 'अपरिभाषित' होने का कारण यह है कि इसे संदर्भ के बिना बुलाया जाता है, इसलिए 'यह' डिफ़ॉल्ट रूप से वैश्विक दायरे से जुड़ा हुआ है। तो (मान लीजिए कि 'lastName' या' firstName' नामक कोई वैश्विक चर नहीं है) दोनों गुणों को 'व्यक्ति' ऑब्जेक्ट से मूल्य प्राप्त करने के बजाय अपरिभाषित किया जाएगा जैसा कि आप उम्मीद कर सकते हैं। –

+0

+1 मैथ्यू क्रूमली ठीक है, धन्यवाद।मैं 'इस' के दायरे को समझता हूं। टाइपो बस विचलित था :-) – Chris22

1

I सोचें अनबाउंड 'यह' कीवर्ड आवश्यक है क्योंकि जावास्क्रिप्ट एक प्रोटोटाइप-आधारित भाषा है। किसी को बेहतर जानकारी दी जा सकती है शायद यहां विवरण भरें।

तथ्य यह है कि यह शायद असहाय है। विशेष रूप से यदि आप एक उच्च क्रम कार्य करने के लिए एक वस्तु की विधि पास करना चाहते हैं, बातें (MooTools से थोड़ी मदद के साथ निम्न उदाहरण) बदसूरत पाने के लिए शुरू:

myArray.each(myObject.foo); 

काम नहीं करेगा, क्योंकि 'इस' myObject.foo में myObject के बजाय myArray का संदर्भ लेंगे। इसके बजाए:

myArray.each(myObject.foo.bind(myObject)) 

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

1

के लिए एक आशुलिपि के रूप में मुहावरा a.f() पर विचार करें:

a.f.call(a); 

यह परिभाषा के द्वारा समारोह f, गुंजाइश a का उपयोग कर के लिए एक कॉल है।

var f = a.f; 
f(); // f.call(this); 
a.f(); // f.call(a); 

तो this और a एक ही वस्तु नहीं हैं, f() और a.f() अलग-अलग दायरों का उपयोग करेगा और इसलिए अलग तरीके से व्यवहार कर सकते हैं।अन्य भाषाओं में स्थिर और वर्ग के तरीकों के बीच के अंतर पर विचार करें:

class Foo { 
public: 
    static void a(Foo *scope) { 
     // do something with given scope 
    }; 

    void b() { 
     a(this); // do something with the scope of this object 
    }; 
}; 

Foo foo; 
Foo bar; 

foo.a(&bar) != foo.b(); // just like f() != a.f() 
foo.a(&foo) == foo.b(); // just like f.call(a) == a.f() 
संबंधित मुद्दे