2012-07-09 14 views
6

मैं अपने सिर को चारों ओर लपेटने की कोशिश कर रहा हूं कि निम्नलिखित कोड परिणाम स्टैक ओवरफ़्लो में क्यों होते हैं जब कोष्ठक शामिल होते हैं, लेकिन जब वे छोड़े जाते हैं तो नहीं।किसी फ़ंक्शन को तर्क के रूप में पास करते समय मुझे ब्रांड्स को क्यों छोड़ना होगा?

मैं फ़ंक्शन को सेटटाइमआउट के लिए एक तर्क के रूप में बुला रहा हूं और यह बिना किसी पैराथेस के काम करता है, लेकिन निश्चित रूप से विफल रहता है जब मैं उन्हें जोड़ता हूं। यह समारोह के बाद() जोड़ने के लिए मेरा अंतर्ज्ञान था। बस उम्मीद है कि कोई मेरे लिए इसे साफ़ कर सकता है। परान वैकल्पिक कब हैं?

मामला 1:

var a = 1; 

function foo() { 
    a++; 
    document.write(a); 
    setTimeout(foo(), 2000) 
}​ 
// RangeError: Maximum call stack size exceeded 

केस 2:

var a = 1; 

function foo() { 
    a++; 
    document.write(a); 
    setTimeout(foo, 2000) 
}​ 
// parens are omitted on foo function and it works. 
+0

शायद एक डुप्लिकेट। इससे मदद मिलनी चाहिए: http://stackoverflow.com/questions/5520155/settimeout-callback-argument/5520190#5520190 –

+0

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

उत्तर

9

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

function foo() { 
    return 5; 
} 

निम्न दो चर घोषणाओं/कार्य पर विचार करें::

निम्नलिखित समारोह मान लें

var one = foo(); 
var two = foo; 

क्या मूल्यों इन चरों है? संख्या 5 - - one को

पहले मामले में हम को क्रियान्वित करनेfoo समारोह और अपनी वापसी मान निर्दिष्ट कर रहे हैं। दूसरे मामले में हम foo स्वयं निर्दिष्ट कर रहे हैं - अधिक सटीक, foo का संदर्भ - two पर। समारोह कभी निष्पादित नहीं किया जाता है।

इस ज्ञान और समझ है कि setTimeout अपनी पहली तर्क एक संदर्भ एक समारोह के रूप में की उम्मीद के साथ

, यह स्पष्ट क्यों अपने पहले मामले में विफल रहता है होना चाहिए, लेकिन एक दूसरे के काम करता है।

बेशक, आपकी समस्या इस तथ्य से अधिक उत्साहित है कि जिस कार्य को आप निष्पादित कर रहे हैं वह स्वयं के लिए एक रिकर्सिव कॉल है। यह हमेशा के लिए हमेशा के लिए चला जाएगा - हमेशा के लिए कुछ परिभाषा के लिए - क्योंकि रिकर्सन को समाप्त करने के लिए कोई आधार मामला नहीं है।

+0

उत्कृष्ट उत्तर, धन्यवाद। –

+0

मुझे अब पूछना चाहिए, अगर आप एक तर्क के साथ foo फ़ंक्शन का संदर्भ देना चाहते हैं तो क्या होगा? जैसे सेटटाइमआउट (फू (एक्स), 2000)। अब मैं समझता हूं कि यह स्पष्ट रूप से एक ढेर ओवरफ्लो में परिणाम देगा, लेकिन क्या पहले फंक्शन संदर्भ में तर्क पारित करना संभव है? –

+0

@ChrisM - हां, उस मामले में सबसे अच्छी बात यह है कि एक अज्ञात फ़ंक्शन का संदर्भ पास किया जाता है जो तब वांछित फ़ंक्शन को कॉल करता है। इस तरह: 'सेटटाइमआउट (फ़ंक्शन() {foo (x)}, 2000) ' –

9

लेखन

foo() 

आप वास्तव में उस पल में foo को कॉल कर रहे हैं। निश्चित रूप से फिर से foo() को कॉल करता है ... जब तक आप stackoverflow नहीं।

यदि आप 2 को प्रभावी ढंग से "संदर्भ" पास कर रहे हैं, तो "इसे 2s में चलाएं" कहें। वास्तव में foo() नहीं बुला रहा है।

तो जब आप वास्तव में इसे आमंत्रित करना चाहते हैं तो माता-पिता का उपयोग करें। जब आप इसका संदर्भ नहीं लेना चाहते हैं।

+0

उदाहरण के तौर पर, 'var foo = (function() {alert ("Hello");}) को चलाने का प्रयास करें,' आपके कंसोल में; फिर, 'var foo = (function() {alert ("Hello");})() हैलो);})()' - ध्यान दें कि कथन के अंत में माता-पिता वास्तव में परिभाषित होने पर फ़ंक्शन को वास्तव में कैसे कहते हैं! –

+0

यह अब मुझे सही समझ में आता है। मैं setTimeout (x, y) को x के रूप में दो तर्कों की व्याख्या कर रहा था = आप क्या करना चाहते हैं और y = आप इसे कितनी बार करना चाहते हैं। मेरी गलतफहमी के लिए मैं foo को कॉल करना और निष्पादित करना चाहता था, और इसे हर 2 सेकंड में करना चाहता था। आपके उत्तर के लिए धन्यवाद! –

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