2012-12-25 130 views
6

我在塊範圍中定義函數時遇到了問題。考慮下面的程序:函數聲明或函數表達式

try { 
    greet(); 

    function greet() { 
     alert("Merry Christmas!"); 
    } 
} catch (error) { 
    alert(error); 
} 

我希望這個節目提醒Merry Christmas!。然而,在Firefox是給我下面的ReferenceError

ReferenceError: greet is not defined 

在歌劇和鉻它提醒問候,因爲我預料到。

很明顯,Firefox將對象範圍內的功能視爲FunctionExpression,而Opera和Chrome將其視爲FunctionDeclaration

我的問題是爲什麼Firefox的行爲不同?哪個實施更合乎邏輯?哪一個是符合標準的?

我知道JavaScript中的聲明是懸掛的,所以如果在同一個作用域中的兩個或多個不同的塊中聲明瞭相同的函數,那麼會出現名稱衝突。

但是那豈不是更合乎邏輯的每一個它的聲明時重新聲明的功能,這樣就可以做這樣的事情:

greet(); // Merry Christmas! 

function greet() { 
    alert("Merry Christmas!"); 
} 

greet(); // Happy New Year! 

function greet() { 
    alert("Happy New Year!"); 
} 

我認爲這將是非常有用的,除了解決塊我上面描述的範圍問題。

+0

「每次聲明函數時都會重新聲明函數,以便您可以這樣做」 - 它們*被重新引用,只有聲明出現一次並且被掛起。你有沒有在前一段中確認你瞭解吊裝? – katspaugh

+2

是的,我確實理解JavaScript中的提升。不,我的判決非常清楚。我想說的是,每當解釋器遇到一個'FunctionDeclaration'(每次聲明_時),它都應該將它提升到之前在同一範圍內函數的聲明(_redeclare the function_)。由於該功能在JavaScript中不存在,因此您不能通過引用當前JavaScript標準來使其無效。這只是一個建議。建議在JavaScript中實現同一個函數的多個聲明。希望能給你帶來一些清晰。聖誕節@ katspaugh –

+0

哦,我明白了。感謝主,它在ES板上不會出現任何人。聖誕快樂,阿迪特! :) – katspaugh

回答

5

實際上,塊範圍內的函數聲明明確地是而不是標準化,並且行爲是實現相關的。不同的實施反應不同。如果你試圖在if語句中聲明一個函數,你會得到相同的奇怪。

ES5規範建議實現者將塊內的函數聲明標記爲警告或錯誤。

+0

所以你不應該在塊範圍內聲明函數。也許這是一個很好的編程習慣。在javascript旁邊的 –

+0

是async lang。所以你需要定義你的函數,然後纔可以調用它。 – Omiga

+0

@ Janim007,這個問題的關鍵在於,在JavaScript定義之前,你可以調用一個拓撲函數。 – katspaugh