2012-10-02 75 views
0

我的問題基本上是這一個的擴展: var functionName = function() {} vs function functionName() {}。 我已閱讀所有答案,但我認爲我仍然錯過了這個問題的答案:Javascript:函數聲明類型對於setInterval和onComplete非常重要?

爲什麼函數聲明的類型對jQuery的onComplete事件和本機setInterval方法很重要?而且,爲什麼它們對於這些而言很重要,但對於普通的addEventListener來說卻不重要?

用的onComplete事件實例(假設blinkOn()叫):

//like this the onComplete event works normally and the functions call eachother 
function blinkOn() { $blink.fadeIn(500, blinkOff); } 
function blinkOff() { $blink.fadeOut(500, blinkOn); } 

//like this blinkOff won't be called after the fadeIn 
function blinkOn() { $blink.fadeIn(500, blinkOff); } 
var blinkOff = function() { $blink.fadeOut(500, blinkOn); }; 

例在使用setInterval:

//works fine 
var timer = setInterval(onTimer, 700); 
function onTimer() { ... } 

//won't work 
var timer = setInterval(onTimer, 700); 
var onTimer = function() { ... } 

我想知道的原因是因爲我想在我的代碼的一致性。如果唯一的方法是使用function a() { ... },那沒問題。但我認爲var a = function() { ... }在定義範圍中更清晰。我真的很好奇。

+0

你在另一個函數中定義了'var onTimer'函數,還是在全局範圍內? – SexyBeast

+0

它與jQuery,native addEventListener或setInterval無關 - 所有工作都一樣。 – Bergi

回答

2

如果你要定義你的函數上面的函數調用,你沒有任何問題。

var toggleLight = function(){light =!light; };

setInterval(toggleLight,500);

你的問題是你正試圖訪問那些還不存在的東西。

這是完全一樣的東西試圖做到這一點:

當程序命中cab不存在。

這個作爲發生在三個步驟,爲每一個功能:

var a = 12, 
    b = 3, 
    c = add(a, b); 

function add (a, b) { return a + b; } 

STEP 1。
引擎抓取了指定的函數add,並找出它的作用(首先定義所有命名函數)。

STEP 2.
發動機定位在函數中的所有變量,並將它們設置爲undefined

var a = undefined, 
    b = undefined, 
    c = undefined; 

function add(a, b) { return a + b; } 

STEP 3.
發動機初始化所有變量中。

// 3.1 
var a = 12, 
    b = undefined, 
    c = undefined; 


// 3.2 
var a = 12, 
    b = 3, 
    c = undefined; 

// 3.3 
var a = 12, 
    b = 3, 
    c = add(a, b); // = return a + b = 15 

所以做這樣的事情:

callFunction(myFunc); 
var myFunc = function() {}; 

等於這樣的:

var myFunc = undefined; 
callFunction(myFunc); 
myFunc = function() {}; 

解決方案:

獨立您實現您的行動。 確保在調用任何東西之前,所有內容都已定義好。

+0

啊,謝謝,我現在看清楚了!它讓我如此糾結爲什麼函數聲明中的差異可能導致這種情況。我只是認爲命名函數是一個簡寫(完全相同)。但是,當你描述它時,它總是有意義的。在我的代碼中沒有工作的情況都與訂單有關。 – navFooh

+0

這不是一個簡寫。你甚至可以命名分配給變量的函數:var myFunc = function yourFunc(param){doStuff(param); };這對遞歸等事情很有用(它可以通過函數名稱來代替變量名稱來調用它自己)。但是,即使這樣會超過'undefined'方面,你也不能使用函數名稱,(只有聲明的函數是這樣工作的 - 即使它的名字不能在'='的右邊, ')。有一點要記住,但是 - 如果你在另一個函數體內調用一個函數,在調用它之前不需要定義 – Norguard

+0

。這裏是我的意思:'var func2 = function(data){func1(data),func1 = function(data){doStuff(data); };'。在這種情況下'func2'知道'func1',就像我說的,當func2被創建時,func1仍然是undefined。但是在調用func2之前不需要定義它,因爲變量的分辨率在最後一秒發生,當一個函數被調用時。這個工作和你遇到的問題之間的區別在於你將'undefined'傳遞給其他函數(比如'setTimeout')。你明白了。 – Norguard

1

命名的函數有點不知道,所以它們變成全局可用的範圍,它們被定義的範圍內,作爲匿名函數分配給一個標識符只有在它們綁定的標識符被定義之後纔可用。

所以你遇到的是一個簡單的競態條件問題。您的第一個非工作示例應該在blikOff變量定義後調用blinkOn()

你的第二個非工作的例子,因爲onTimer當調用setInterval尚未確定不起作用。在調用setInterval之前移動變量定義,它將起作用。

+0

+1,但「有點在哪裏創造」? – bfavaretto

+0

是的,那是我想到的第一個非技術性的限制:) – ndm

+0

哈哈它確實捕捉到了精神。但現在我想更多的是堅持命名函數。將所有邏輯與動作分開是有吸引力的......但是我認爲在他們自己的範圍內全局可用的函數中沒有任何傷害?只要能夠在他們自己的範圍內的任何地方給他們打電話似乎更像是一種優勢,或者不是? – navFooh

0
//like this blinkOff won't be called after the fadeIn 
function blinkOn() { $blink.fadeIn(500, blinkOff); } 
var blinkOff = function() { $blink.fadeOut(500, blinkOn); }; 

它會被調用。您只需確保blinkOn不是,在調用之前(上面),調用(引用即可)。