2012-03-02 14 views
6

मैं जल्दी हो जाऊंगा और सीधे मामले में कूद जाऊंगा। कोड पर टिप्पणी की गई है ताकि आप मेरे इरादों को जान सकें। असल में, मैं एक छोटा, HTML5 आधारित गेम बना रहा हूं, और सर्वर पर या कुकी में सामान सहेजने का विरोध करता हूं, मैं केवल खिलाड़ी को एक स्तर कोड प्रदान करूंगा। जब कोई खिलाड़ी कोड इनपुट फ़ील्ड में कोड (एक साधारण हैश के रूप में) में प्रवेश करता है, और उस स्तर को लोड करने के लिए बटन क्लिक करता है, तो फ़ंक्शन "एल" कहा जाता है। वह फ़ंक्शन पहले खिलाड़ी की प्रविष्टियों को पुनर्प्राप्त करता है, फिर हैश की सूची के माध्यम से पुनरावृत्त करता है और उनकी तुलना करता है। जब एक मैच शौकीन होता है, तो उस स्तर को लोड किया जाना चाहिए, लेकिन त्रुटियां थीं। मैंने डीबगिंग का थोड़ा सा किया, और मुझे पता चला कि इटरेटर ("i") का मान सेटटाइमआउट के अंदर बदल गया है! मैं 1 सेकंड रोकना चाहता हूं, क्योंकि स्तर को तुरंत लोड करना बहुत तेज़ होगा और खराब लगेगा।सेटटाइमआउट मेरे चर बदल रहा प्रतीत होता है! क्यूं कर?

levelCodes = //Just a set of "hashes" that the player can enter to load a certain level. For now, only "code" matters. 
[ 
    {"code": "#tc454", "l": 0}, 
    {"code": "#tc723", "l": 1}, 
] 

var l = function() //This function is called when a button is pressed on the page 
{ 
    var toLoad = document.getElementById("lc").value; //This can be "#tc723", for example 

    for (i = 0; i < levelCodes.length; i++) //levelCodes.length == 2, so this should run 2 times, and in the last time i should be 1 
     if (levelCodes[i].code == toLoad) //If I put "#tc723" this will be true when i == 1, and this happens 
     { 
      console.log(i); //This says 1 
      setTimeout(function(){console.log(i)}, 1000); //This one says 2! 
     } 
} 
+1

अच्छी टिप्पणी, सभी upvotes है। – ninjagecko

+0

एफवाईआई, आपका कोड कई कारणों से जेएसलिंट पास नहीं करता है और कुछ ब्राउज़रों में त्रुटियों का उत्पादन करेगा –

+0

@ मार्कस्कुल्थिस, कृपया समझाएं, मुझे लगता है कि जेएसलिंट किसी प्रकार का मूल्यांकनकर्ता है, क्या यह सही है? खैर, क्या आप मुझे बता सकते हैं कि यह गणना क्यों नहीं करती? – corazza

उत्तर

3
पाश के लिए

लगातार i वृद्धि कर देता है जब तक पाश की स्थिति उत्पन्न होने, भले ही पाश के लिए में कोड निष्पादित नहीं करता है, जब setTimeout में कोड यह i की वर्तमान मूल्य से पता चलता कार्यान्वित - जो 2 है।

4

ईसीएमएस्क्रिप्ट lexical closures की तकनीक का उपयोग करता है जो सभी मूल संदर्भ वस्तुओं/शब्दावली पर्यावरण रिकॉर्ड (ES3/ES5) के आंतरिक संग्रहण से कुछ और नहीं है।

संक्षेप में, setTimeout द्वारा उपयोग किया गया आपका अनाम कार्य उस i चर पर बंद हो जाता है, इसलिए जब टाइमआउट "प्रतीक्षा" हो जाता है, तो आपका लूप जारी रहता है। setTimeout asynronously निश्चित रूप से operatores और कि बारी में मतलब है, समय है कि पाश मूल्य समाप्त हो गया है, तो i पाठ्यक्रम 2.

अब बंद सामान के बारे में याद की है, setTimeout में हमारे गुमनाम समारोह अभी भी i जब के लिए एक संदर्भ रखती है यह अंत में आग (1000ms के बाद)। तो इसे सही ढंग से आप 1000ms के बाद प्रत्येक यात्रा के लिए संख्या दिखाना चाहते हैं तो आप में से 2.

मूल्य से पता चलता है, तो आप एक और संदर्भ को लागू करने की जरूरत है। यह

setTimeout((function(local) { 
    return function() { 
     console.log(local); 
    }; 
}(i)), 1000); 
+0

+1 उदाहरण के लिए स्पष्ट स्थानीय –

5

जैसा दिखता है अन्य लोगों ने पहले से ही आपके द्वारा प्राप्त व्यवहार के कारण को लिखा है। अब समाधान:

(function(i) { 
    setTimeout(function(){console.log(i)}, 1000); 
})(i); 

यह काम करता है, क्योंकि यह अभी तक एक और बंद करने में चर i के वर्तमान मूल्य कैप्चर करता है, और कहा कि बंद के भीतर चर परिवर्तन नहीं करता है: setTimeout लाइन के लिए बदल जाते हैं।

+0

+1 के साथ, लेकिन इसे पूरी तरह स्पष्ट करने के लिए: (function (iwas) { setTimeout (फ़ंक्शन() {console.log (iwas)}, 1000);}) (i); - –

1

समय setTimeout कॉलबैक तक क्योंकि आप पाश और छोड़ने नहीं है, मैं 2 का मान होगा चर निष्पादित करने के लिए हो जाता है मैं गिनती जब तक यह levelCodes.legnth के बराबर है रखता है (जो 2 है)। मूल रूप से आप setTimeout बुला के बाद वापसी जोड़ने के लिए या तोड़ की जरूरत है। इसके अलावा, आप चर मैं की घोषणा नहीं कर रहे हैं, तो यह वैश्विक नामस्थान, जो बुरा है और संभवतः बहुत अस्पष्ट कीड़े पैदा हो सकती है के लिए बाध्य होंगे। उदाहरण के लिए, i का मान अन्य कार्यों में बदला जा सकता है, इसलिए सेटटाइमआउट कॉलबैक एक अलग मान देखेंगे। आपको var i जोड़ने की आवश्यकता है; एल की शुरुआत में

+0

में 'i' को पारित करने से मैंने देखा कि अंतर्निहित वैश्विक चर I –

संबंधित मुद्दे