मैं यह व्याख्यान देख रहा हूँ: http://www.youtube.com/watch?v=Kq4FpMe6cRs

// the speaker states that "'bar' is just some function 
// that invokes whatever function is passed to it"
function bar(fn) {
    fn();
}

function foo() {
    var x = 8;
    bar(function baz() { return x; });
}

Object.prototype.x = 'foo';

मिनट 35 पर, ऊपर दिखाया गया मुद्दा प्रस्तुत किया गया है। व्याख्याता बताता है कि कुछ ब्राउज़र 8 के बजाय foo वापस आ जाएंगे।

क्यों?

बीटीडब्ल्यू, इस प्रश्न को लिखते समय, मैंने इसे समझ लिया, लेकिन मैं इस प्रश्न को वैसे भी पोस्ट करूंगा क्योंकि यह एक दिलचस्प मुद्दा है। :)


लाइव डेमो: http://jsfiddle.net/simevidas/mHyKc/

Opera 11 अलर्ट 'foo', मेरे सभी अन्य ब्राउज़र (IE9 सहित) 8 लौटते हैं।


अपडेट करें: इसका पता लगाने के बारे में मैंने जो कहा है, मैं उसे वापस लेता हूं। नेस्टेड फ़ंक्शन के नामित फ़ंक्शन होने के साथ इसका कुछ संबंध है। यदि आप नाम (baz) हटा देते हैं, तो Opera 8 वापस आ जाता है, जिसका अर्थ है कि समस्या केवल नामित नेस्टेड फ़ंक्शन के साथ होती है।

लेकिन क्यों?

5
Šime Vidas 5 मार्च 2011, 03:38
मैं प्रश्न के बिंदु को समझता हूं, और मुझे विश्वास है कि यह एक महत्वपूर्ण अंतर है, लेकिन इस foo फ़ंक्शन में कुछ कोड-गंध है।
 – 
zzzzBov
5 मार्च 2011, 03:43

1 उत्तर

सबसे बढ़िया उत्तर

मैं मानता हूं कि मैंने इसे देखा। मुझे नहीं लगता कि मैंने इसे इतनी आसानी से समझ लिया होगा, कम से कम कहने के लिए। http://kangax.github.com/nfe/#spidermonkey-peculiarity

समस्या को समझने के लिए, नामित फ़ंक्शन अभिव्यक्तियों का शब्दार्थ आवश्यक है। लिंक को उद्धृत करने के लिए, "एक नामित फ़ंक्शन अभिव्यक्ति का पहचानकर्ता केवल फ़ंक्शन के स्थानीय दायरे के लिए उपलब्ध है।" सीधे तौर पर इसका तात्पर्य है:

var fn = function aNamedFunction() {
  typeof aNamedFunction;  // "function"
};
typeof aNamedFunction;  // "undefined"

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

प्रश्न के कोड नमूने में, x को पहले फंक्शन इनवोकेशन के अंतरतम फ्रेम में देखकर हल किया जाता है। चूंकि फ़ंक्शन बॉडी var x; घोषित नहीं करती है, यह नहीं मिला है और दुभाषिया फ्रेम को एक स्तर ऊपर की जांच करता है, जो डमी फ्रेम है। चूंकि डमी फ्रेम new Object() (या कुछ शब्दार्थ समकक्ष) द्वारा बनाया गया था, डमी फ्रेम में x को देखकर प्रोटोटाइप श्रृंखला को पार किया जाएगा, जैसा कि यह किसी अन्य जावास्क्रिप्ट ऑब्जेक्ट के लिए करता है। इस प्रकार, यह Object.prototype खोजता है, स्ट्रिंग 'foo' को x से बंधा पाता है, और उसे वापस कर देता है।

ES5 के लगातार लेक्सिकल स्कोपिंग के लिए धन्यवाद।

वैकल्पिक पठन: http://dmitrysoshnikov.com/ecmascript/chapter-5 -फ़ंक्शंस/#nfe-and-spidermonkey

4
ide 5 मार्च 2011, 04:07
आह हाँ। मुझे कल्पना में उस रैपर ऑब्जेक्ट के बारे में पढ़ना याद है। इसलिए आइडेंटिफ़ायर रिज़ॉल्यूशन रैपर ऑब्जेक्ट तक पहुंचने के लिए स्कोप चेन को ट्रैवर्स करेगा, और फिर उस ऑब्जेक्ट की प्रोटोटाइप चेन को x तक ले जाएगा। मैं कल्पना नहीं कर सकता कि यह आकस्मिक जावास्क्रिप्ट प्रोग्रामर के लिए कितना भ्रमित करने वाला होना चाहिए :)
 – 
Šime Vidas
5 मार्च 2011, 04:50