還是一樣,先上代碼:
<script> var f = function g() { return 1; }; if (false) { f = function g(){ return 2; }; } alert(g()); // 2</script>
把這段代碼扔到IE 6 裡面和chorme裡面是完全不同的兩種效果。
這裡輸出2 是在ie6裡面的效果,如果在chorme會出現g沒有定義。
這也算是JScript的bug吧。
在這裡很明顯,這裡的只是定義了g的函數運算式而已。包括在if的條件陳述式中,也只是定義了函數運算式,沒有去聲明函數。
那麼這樣直接存取肯定是會出錯的。
那麼對於何為聲明,何為函數運算式呢?
在ECMAScript中,建立函數的最常用的兩個方法是函數運算式和函式宣告,兩者期間的區別是有點暈,因為ECMA規範只明確了一點:函式宣告必須帶有標示符(Identifier)(就是大家常說的函數名稱),而函數運算式則可以省略這個標示符:
function 函數名稱 (參數:可選){ 函數體 }
函數運算式:
function 函數名稱(可選)(參數:可選){ 函數體 }
所以,可以看出,如果不聲明函數名稱,它肯定是運算式,可如果聲明了函數名稱的話,如何判斷是函式宣告還是函數運算式呢?ECMAScript是通過上下文來區分的,如果function foo(){}是作為賦值運算式的一部分的話,那它就是一個函數運算式,如果function foo(){}被包含在一個函數體內,或者位於程式的最頂部的話,那它就是一個函式宣告。
還有一種函數運算式不太常見,就是被括弧括住的(function foo(){}),他是運算式的原因是因為括弧 ()是一個分組操作符,它的內部只能包含運算式。
你可能會想到,在使用eval對JSON進行執行的時候,JSON字串通常被包含在一個圓括弧裡:eval('(' + json + ')'),這樣做的原因就是因為分組操作符,也就是這對括弧,會讓解析器強制將JSON的花括弧解析成運算式而不是代碼塊。