2009-12-19 9 views
6

का भ्रमित संचालन मैंने var कीवर्ड के साथ एक बहुत अजीब (मेरे लिए) समस्या में भाग लिया है। मैंने इसे काफी कम परीक्षण केस में कम कर दिया है, और पाया कि यह नोड.जेएस (इस प्रकार, वी 8 और क्रोम), सफारी 4 के इंस्पेक्टर (इस प्रकार, नाइट्रो), और फायरबग (जाहिर है, स्पाइडरमोन्की) में प्रदर्शित किया गया है। मैं मूल रूप से एक बग रिपोर्ट तैयार कर रहा था, लेकिन चूंकि यह इतना व्यापक रूप से प्रदर्शित होता है, इसलिए मुझे लगता है कि मैं पूरी तरह से गलत समझता हूं कि जावास्क्रिप्ट को किस प्रकार गुंजाइश और चर दिखाना चाहिए।जावास्क्रिप्ट `var` कीवर्ड

परीक्षण केस बहुत छोटा है, और यहां गिटहब पर: http://gist.github.com/260067। पहले और दूसरे उदाहरण के बीच एकमात्र अंतर var कीवर्ड शामिल करना है। https://gist.github.com/698b977ee0de2f0ee54a

संपादित करें:: कैसे व्यापक गुंजाइश काम करता है समझाने के लिए प्रयास करने से किसी भी अधिक जवाब रोकता करने के लिए, मैं

यहाँ, साथ ही, एक ऐसी ही परीक्षण का मामला है कि एक अलग तरीके से एक ही 'समस्या' दर्शाती है मैं इसके साथ गहराई से परिचित हूँ। मेरे समस्या यह है कि मुझे समझ नहीं आता क्यों निम्नलिखित कोड 'काम करता है' है (कि यह alert() s 'बाहरी', ', भीतरी' और उसके बाद फिर 'बाहरी' के बाद):

(function(){ 
    var foo = 'outer'; 
    alert("Outer `foo`: " + foo); 

    (function(){ 
    foo = 'inner'; 
    alert("Inner `foo`: " + foo); 

    var foo; 
    })(); 

    alert("Outer `foo`: " + foo); 
})(); 

var foo;foo के पुन: असाइनमेंट के लिए पूरी तरह से अप्रासंगिक स्थिति में होता है; तो यह असाइनमेंट को बहुत ही महत्वपूर्ण तरीके से क्यों प्रभावित करता है?

+0

आप एक eval का उपयोग क्यों कर रहे हैं? आपके द्वारा पोस्ट किए गए कोड में eval का उपयोग करने का बिल्कुल कोई कारण नहीं है। समस्या का प्रदर्शन करने के लिए – Marius

+0

। वास्तविक कार्यान्वयन बहुत अलग है; आप इसे यहां जंगली में देख सकते हैं: http://github.com/elliottcable/poopy.js/blob/new-acquire/lib/from.js#L193 – ELLIOTTCABLE

+0

आपका अंतिम उदाहरण काम करता है क्योंकि 1) foo = 'inner'; पैरेंट स्कोप foo को मान निर्दिष्ट करता है, जिसे इस फ़ंक्शन तक पहुंच है। 2) आपको एक चर घोषित करने के लिए var का उपयोग करने की आवश्यकता नहीं है। – Marius

उत्तर

14

बात यह है कि अन्य भाषाओं के विपरीत, जावास्क्रिप्ट किसी फ़ंक्शन की शुरुआत में सभी चर बनाता है। इसका मतलब है कि कोड:

(function(){ 
    if(myVar == undefined){ 
     alert(myVar); 
    } 
    if(myVar == undefined){ 
     var myVar = 5; 
    } 
})(); 

वास्तव में संकलित और एक चर बनाने के लिए और अगर या पाश ब्लॉक, आप let उपयोग करने के लिए केवल यह एक अंदर उपलब्ध

(function(){ 
    var myVar; 
    if(myVar == undefined){ 
     alert(myVar); 
    } 
    if(myVar == undefined){ 
     myVar = 5; 
    } 
})(); 

रूप में व्याख्या की है, जो है एक नई जावास्क्रिप्ट सुविधा। मुझे यकीन नहीं है कि अभी तक कितने ब्राउज़र इसे कार्यान्वित करते हैं (फ़ायरफ़ॉक्स 3.5 करता है यदि आप <script type="text/javascript;version=1.7"> का उपयोग करते हैं)।

(function(){ 
    if(myVar == undefined){ 
     alert(myVar); 
    } 
    if(myVar == undefined){ 
     let myVar = 5; 
    } 
})(); 
+0

हां, मुझे इसके बारे में पता है, ऊपर अम्नोन को मेरी प्रतिक्रिया देखें। मेरा भ्रम इस तथ्य से उत्पन्न होता है कि यह स्थानीय दायरे में परिभाषित होने से पहले * से कॉल को प्रभावित करता है *। – ELLIOTTCABLE

+0

हां, आखिर में मैंने आपका प्रश्न समझा, और मेरा जवाब दोबारा लिखा। उम्मीद है की यह मदद करेगा। – Marius

+0

हां, इससे काफी मदद मिली। मूल प्रश्न में मेरी स्पष्टीकरण देखें। मैं स्पष्ट रूप से अभी भी समझ नहीं पा रहा हूं कि ऐसा क्यों होता है; मुझे लगता है कि जावास्क्रिप्ट की मेरी अंतर्ज्ञानी समझ, भाषा, विनिर्देश/कार्यान्वयन के अनुरूप नहीं है। भले ही, मैं इस उत्तर को 'स्वीकृत' के रूप में चिह्नित करने जा रहा हूं।/= – ELLIOTTCABLE

1

var का समावेश शामिल है कि {} का असाइनमेंट वैश्विक परिवर्तनीय निर्यात के बजाय स्थानीय चर निर्यात में किया जाता है, जिसका अर्थ है कि इसका कोई प्रभाव नहीं है।

+0

हां। मैं समझता हूँ। मैं * मूल जावास्क्रिप्ट जानता हूँ। मेरी समस्या यह है कि * उस * कॉल के बाद आता है जिसे हम देख रहे हैं; इसका ध्यान इस बात पर कोई प्रभाव नहीं होना चाहिए कि 'अलर्ट() 'कॉल के समय' निर्यात' को परिभाषित नहीं किया गया है या नहीं। इसके बाद जो भी आता है, उस समय 'निर्यात' * * अनिश्चित नहीं है। – ELLIOTTCABLE

2

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

संपादित करें: let कीवर्ड अधिक पारंपरिक रूप से काम करता है (यह केवल युक्त ब्लॉक के लिए एक चर घोषित करता है) लेकिन यह जावास्क्रिप्ट के सभी संस्करणों में उपलब्ध नहीं है।

+0

तो दुभाषिया आगे पढ़ता है, और परिवर्तनीय की घोषणा को नोटिस करता है ... और लोकल स्कोप ('अपरिभाषित' से जुड़ा हुआ) में चर की परिभाषा, तर्क के ओवरराइड करता है? यह * अत्यंत * काउंटर-सहज ज्ञान युक्त है। इस उदाहरण में दुभाषिया आगे कैसे पढ़ता है? ओ.ओ – ELLIOTTCABLE

+1

हां यह प्रति-अंतर्ज्ञानी है, लेकिन यह है कि यह कैसे है ... यह कैसे किया जाता है इसके बारे में, फ़ंक्शन को चलाने से पहले पार्स किया जाता है। – Amnon

+0

"" "इस उदाहरण में दुभाषिया आगे कैसे पढ़ता है?" "" - यह हर उदाहरण में आगे दिखता है। यह कुछ अन्य भाषाओं की तरह "रेखा से लाइन" पार्स/दुभाषिया नहीं है, पार्सर कुछ भी निष्पादित करने से पहले सभी स्क्रिप्ट पढ़ता है। – Hejazzman