2012-07-09 17 views
6

Aşağıdaki kodun parantezler dahil edildiğinde neden taşmasıyla sonuçlandığı konusunda kafamı kaydırmaya çalışıyorum ancak atlanmadıklarında bunu yapmam.Bir işlevi argüman olarak geçirirken neden parantez atmalıyım?

Ayarın kendisini setTimeout için bir argüman olarak çağırıyorum ve parantez olmadan çalışıyor, ancak eklediğimde elbette başarısız oluyor. Fonksiyondan sonra() eklemek benim sezgisimdi. Umarım birileri bunu benim için temizleyebilir. Paraleller ne zaman isteğe bağlı ve değil?

DURUM 1:

var a = 1; 

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

DURUM 2:

var a = 1; 

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

Muhtemelen bir çift. Bu yardımcı olmalıdır: http://stackoverflow.com/questions/5520155/settimeout-callback-argument/5520190#5520190 –

+0

teşekkür ederim çok lwburk, bu bağlantıdaki açıklamanız benim için temizlenmiş şeyler. –

cevap

9

Bu soru genellikle setTimeout referans alınarak ilk kez sorulmuştur, ancak bence bu davranışın bu işleve özgü olmadığını belirtmek önemlidir. Sadece parantezin ne yaptığını ve onları bırakmanın ne anlama geldiğini anlamanız gerekir.

function foo() { 
    return 5; 
} 

aşağıdaki iki değişken bildirimleri/atamalarını düşünün:

aşağıdaki işlevi varsayalım bu değişkenler var mı hangi değerleri

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

? numara 5 - - one ilk durumda

biz foo işlevi yürütme ve dönüş değeri atamak konum. İkinci durumda, foo'un kendisinin - daha doğrusu, foo - two - referansını ataıyoruz. Fonksiyon asla gerçekleştirilmez. Bu bilgi ve setTimeout ilk argüman bir işleve bir referans olarak beklediği bir anlayışla

, ilk davan başarısız neden açık olmalı, fakat ikincisi çalışır.

Tabii ki, yürütmekte olduğunuz işlevin kendi kendine bir özyinelemeli çağrı olması gerçeğiyle ilgili sorununuzu daha da kötüleştiriyor. Bu sonsuza dek sürecek - sonsuza dek bazı tanımlamalar için - özyinelemeyi sona erdirecek bir temel durum olmadığı için.

+0

mükemmel cevap, teşekkürler. –

+0

Şimdi sormalıyım, ya foo işlevini bir argümanla referans almak isteseydiniz? Örneğin. setTimeout (foo (x), 2000). Şimdi bunun açıkça bir yığın taşmasıyla sonuçlanacağını anlıyorum, ancak ilk işlev referansında bir argümanı iletmek mümkün mü? –

+0

@ChrisM - Evet, bu durumda yapılacak en iyi şey, daha sonra istenen işlevi çağıran anonim bir işleve başvurmaktır. Bunun gibi: 'setTimeout (function() {foo (x)}, 2000)' –

9

aslında o an foo aradığınız

foo() 

yazarak. Hangisi daha sonra foo() 'yı tekrar çağırırsınız ...

2. durumda, "bunu" 2s'de çalıştır "diyerek" referans "kelimesini etkin bir şekilde geçiriyorsunuz. Aslında foo() çağırmıyor.

Bu nedenle, gerçekten çağırmak istediğinizde parantez kullanın. Başvurmak istediğiniz zaman değil.

+0

Örnek olarak, konsolunuzda 'var foo = (function() {alert (" Hello ");})' yi çalıştırmayı deneyin; sonra, var foo = (function() {alert ("Hello");})() '- çalıştırmayı deneyin deyimin sonunda parens aslında tanımlandığı gibi işlevi çağırmak nasıl! –

+0

bu, şimdi bana mantıklı geliyor. İki argümanı yorumlamak içinTimeout (x, y) olarak x = ne yapmak istiyorsunuz ve y = ne sıklıkla yapmak istiyorsunuz. Yanlış anlaşılmamı istemek ve foo yürütmek istedim ve her 2 saniyede bir yapmak. Cevabınız için teşekkürler! –

İlgili konular