2011-01-05 11 views
21

कोड के निम्न ब्लॉक को चलाने पर, एफएफ और क्रोम आउटपुट typeof(hiya) = string जबकि आईई 7/8 आउटपुट typeof(hiya) = undefinedआईई नूक विंडो क्यों करता है। एबीसी चर?

  • एक भी <script> ब्लॉक में सब कुछ का मेल:

    <html> 
        <body> 
         <script type="text/javascript"> 
          window.hiya = 'hiya'; 
         </script> 
         <script type="text/javascript"> 
          if(false) { 
           var hiya = 1; 
          } 
          document.write("typeof(hiya) = "+ typeof(hiya)); 
         </script> 
        </body> 
    </html> 
    

    निम्नलिखित में से हर समस्या का समाधान करता है।

  • if ब्लॉक को हटा रहा है।
  • var hiya = 1 से var hiya2 = 1 का नाम बदल रहा है।
  • var hiya = 1 से window.hiya = 1 का नाम बदल रहा है।
  • var hiya = 1 को hiya = 1 का नाम बदल रहा है।

क्या हो रहा है? क्या आईई में कोई स्कोपिंग बग है?

+1

पहली जगह ऐसी मुश्किल चीजें क्यों नहीं लिख रहे हैं? ;) – delnan

+1

हां। असली दुनिया की समस्या जो मैं कर रहा था वह बहुत जटिल था, जहां एक सशर्त था जो किसी अन्य पुस्तकालय को लोड नहीं होने पर कुछ परिभाषित करेगा। यह कुछ है जो मैं चारों ओर काम कर सकता हूं, लेकिन मैं वास्तव में समझना चाहता हूं कि ऐसा क्यों होता है। – etoleb

+4

@ डेलनान: स्नारकी, हुह? मैंने सोचा कि यह बहुत स्पष्ट था कि यह वास्तविक कोड नहीं था, यह केवल एक कमी है जो समस्या को दिखाती है। सभी ओपी की तरह एक प्रश्न पोस्ट करने से पहले करना चाहिए। –

उत्तर

21

आईई गूंगा है, यह पहचान नहीं करता है कि window.varName और var varName कुछ मामलों में समान चर का उपयोग करता है।

जब कोई नया स्क्रिप्ट टैग सामना किया जाता है, तो यह पहले var के साथ घोषित सभी चर शुरू करता है। यह var कथन नहीं चलाता है (वह भाग जो इसे "hiya" में प्रारंभ करेगा)। यह सिर्फ इसे अपरिभाषित करने के लिए शुरू करता है। ऐसा नहीं होगा अगर इसे पहले var के साथ घोषित किया गया था।

यदि आपका कोड एक ही स्क्रिप्ट टैग में था, तो यह त्रुटि नहीं होगी। इसके अलावा, अगर हिया की पहली घोषणा var के साथ की गई थी, तो यह त्रुटि भी नहीं होगी।

विशेष रूप से, आपके दूसरे स्क्रिप्ट टैग में, आईई पहले var स्टेटमेंट्स की तलाश करता है, यह एक var var hiya = 1 पाता है; फिर यह कहता है, हिया को पहले एक विविध बयानों के साथ शुरू नहीं किया गया था (आईई गूंगा है, अन्य ब्राउज़र पहचानते हैं कि खिड़की .hiya वही काम करता है) और किसी भी कोड को निष्पादित करने से पहले hiya, overwriting window.hiya को शुरू करता है।

संभावित समाधान:

  • एक ही स्क्रिप्ट टैग के अंतर्गत अपने कोड रखें
  • window.hiYa
  • साथ चर प्रारंभ न करें आप लिपियों में से एक पर नियंत्रण नहीं है, तो यह सुनिश्चित कर लें स्क्रिप्ट का उपयोग करता है जो स्क्रिप्ट का उपयोग करता है

अंतिम नोट यह स्पष्ट करने के लिए कि जेएस पार्सर्स आपके कोड में क्या करते हैं।

<html> 
    <body> 
     <script type="text/javascript"> 
      window.hiya = 'hiya'; 
     </script> 
     <script type="text/javascript"> 
      // IE is dumb, it doesn't recognize that hiya is already 
      // defined as window.hiya, so it's initialized to undefined here 
      var hiya; 
      if(false) { 
       hiya = 1; 
      } 
      document.write("typeof(hiya) = "+ typeof(hiya)); 
     </script> 
    </body> 
</html> 

तो अगर आप एक स्क्रिप्ट टैग में सब कुछ डाल दिया, यह क्या कोड होगा (के बाद जे एस इंजन के लिए वर बयान ले जाया गया है: जे एस पार्सर अपने कोड को देखता है, तो यह निम्नलिखित में परिवर्तित हो शीर्ष), ताकि आप देख सकें कि आईई इसे गड़बड़ कर सकता है, क्योंकि आपके window.hiya असाइनमेंट शीर्ष पर स्थानांतरित होने वाले var के बाद होगा।

<html> 
    <body> 
     <script type="text/javascript"> 
      var hiya; 
      window.hiya = 'hiya'; 
      if(false) { 
       hiya = 1; 
      } 
      document.write("typeof(hiya) = "+ typeof(hiya)); 
     </script> 
    </body> 
</html> 
+0

तो 'window.foo' के माध्यम से एक चर को उजागर करना, फिर एक अलग निष्पादन संदर्भ में वैश्विक दायरे में' var foo' घोषित करना आईई को गड़बड़ कर देगा। जेस्क्रिप्ट ऐसी "अद्वितीय" चीज है। भले ही यह एक दुर्लभ कोने का मामला है, फिर भी ध्यान में रखना एक अच्छी बात है। –

+0

@ FabrícioMatté यह एक कोने के मामले में इतना नहीं है। यदि आप एकाधिक ढांचे का उपयोग कर रहे हैं और वे दोनों नेमस्पेस बनाते हैं (एक 'var' और' विंडो [प्रॉपर्टी] 'का उपयोग करते हुए एक, आपको त्रुटि मिल जाएगी। मुझे इसे एक्सटी-जेएस और Google क्लोजर टेम्पलेट्स का एक साथ उपयोग करके मिला। –

+0

आईई में वही बात होती है यदि आप एक टैग में एक स्क्रिप्ट में कॉल करते हैं, और किसी अन्य टैग में एक चर का उपयोग करते हैं। इस तरह: ' ' – Navigatron

10

मूल समस्या को यहां देखा जा सकता है http://jsfiddle.net/Raynos/UxrVQ/ मुझे अभी तक यह पता लगाना नहीं है कि क्यों आईई विंडो के बिना खिड़की को ओवरराइट करता है।

[संपादित करें]

विनिर्देश से। पृष्ठ 38:

प्रत्येक VariableDeclaration या कोड में VariableDeclarationNoIn के लिए, चर वस्तु जिसका नाम की संपत्ति बनाने में पहचानकर्ता VariableDeclaration या VariableDeclarationNoIn, जिसका मूल्य अपरिभाषित है और जिसका गुण हैं है कोड के प्रकार से निर्धारित । परिवर्तनीय ऑब्जेक्ट की संपत्ति पहले से ही घोषित चर के नाम से है, संपत्ति का मान और इसकी विशेषता परिवर्तित नहीं है।

एक संभावित व्याख्या हो सकता है कि वैश्विक क्षेत्र में आईई window वस्तु और वैश्विक क्षेत्र के लिए जब चर घोषित करने variable object बीच अंतर। वैकल्पिक रूप से window ऑब्जेक्ट पर एक प्रॉपर्टी सेट करना शायद उसी संपत्ति को variable ऑब्जेक्ट पर सेट न करें। यदि आप एक औपचारिक जेस्क्रिप्ट विनिर्देश पा सकते हैं या आईई का स्रोत आसपास झूठ बोल रहा है तो हम यह पता लगा सकते हैं कि क्विर्क क्या है।

[/ संपादित करें]

@TimDown & @JuanMendes उनका कहना है कि साथ कि क्या विंडो ऑब्जेक्ट के लिए किसी प्रॉपर्टी लेखन एक चर घोषणा है एक मुद्दा है के लिए धन्यवाद।

मुद्दा:

चर घोषणा ब्लॉक के शीर्ष करने के लिए ले जाया गया हो जाता है। भले ही कोड मर गया हो। किसी कारण से आईई में यह हिया को स्थानीय चर के रूप में घोषित करेगा, भले ही यह विंडो पर संग्रहीत उसी नाम की संपत्ति के साथ कक्षाएं हों।

स्पष्टीकरण:

क्या हो रहा है अपने एक चर हिया बुलाया घोषणा की कि है। Var कथन स्वचालित रूप से ब्लॉक के शीर्ष पर हटा दिया जाता है। एक अगर कथन एक ब्लॉक नहीं है, तो एक समारोह है। तो अगर ब्लॉक ब्लॉक में कोड कभी नहीं चला जाता है तो वैरिएबल अभी भी घोषित हो जाता है।

फ़ायरफ़ॉक्स में यह उस विंडो को पहचान लेगा .hiya hiya की घोषणा है।

आईई में दूसरे पटकथा में घोषणा यह अधिलेखित कर देता है

क्या यह actaully

कर रहा है Firefox में:

// script block 1 
var hiya; // window.hiya counts as a declaration 
window.hiya = "hiya"; // set 

// script block 2 
if (false) hiya = 1; 
document.write(...) 

आईई में:

// script block 1 
window.hiya = "hiya"; 

// script block 2 
var hiya; // redeclared here because window.hiya "isn't" a declaration 
if (false) hiya = 1; 
document.write(...) 

समाधान बस नामस्थान है। आप दो स्थानों पर एक ही नाम का उपयोग कर रहे हैं और इसे दो अलग-अलग नामों में एक्सेस कर रहे हैं। स्थानीय क्षेत्र देने के लिए या तो अलग-अलग नामों का उपयोग करें या बंद करें।

+0

हां, मैं 'विंडो 'के भीतर' hiya' नामक एक चर घोषित करता हूं (जो इसे 'hiya' के रूप में सुलभ बनाता है) और जब मैं एक' if' ब्लॉक जोड़ता हूं जिसमें स्थानीय 'var hiya = ..' कथन होता है तो यह कारण होगा 'window.hiya' को अपरिभाषित किया जाना चाहिए (भले ही अगर ब्लॉक कभी निष्पादित नहीं किया गया था)। – etoleb

+0

कोड की लाइन निष्पादित नहीं की गई है। यह अभी भी एक पार्स हो जाता है और परिवर्तनीय घोषणा संकलन समय पर संभाली जाती है बल्कि फिर समय चलती है। – Raynos

+0

यह उत्तर सही नहीं है। यदि आप आईई में अपना कोड चलाते हैं, तो आप देखेंगे कि हिया "हिया" पर सेट है। इस समस्या की कुंजी यह है कि दो अलग-अलग स्क्रिप्ट टैग हैं। मेरा जवाब देखें –

3

आप क्या सामना करना पड़ा की वजह से है:

  1. var एक बयान किया जा रहा
  2. जे एस में कोई ब्लॉक गुंजाइश
  3. बयान निष्पादित हो से पहले कोड चलाता

तो क्या होता है नहीं है कि जावास्क्रिप्ट किसी भी अन्य से पहले var कथन निष्पादित करेगा, लेकिन यहके लिए असाइनमेंट अभिव्यक्ति का मूल्यांकन नहीं करेगाundefined के मान के लिए डिफ़ॉल्ट होगा।

जैसा कि रेनोस ने पहले ही कहा है कि आईई प्रत्येक स्क्रिप्ट को अपने आप निष्पादित करेगा, इसलिए ऊपर वर्णित व्यवहार, hiya को अपरिभाषित किया जाएगा।

+1

रेनोस का जवाब गलत है। सभी ब्राउज़र एक अलग प्रोग्राम के रूप में प्रत्येक '