2013-01-09 41 views
11

運行此在Chrome和Firefox提供了不同的答案:的Javascript吊裝Chrome和Firefox

(function() { 

     if(true) { 
      function f() { alert("yes"); }; 
     } else { 
      function f() { alert("no"); }; 
     } 
     f(); 

    })(); 

在Chrome中的結果是「不」 在Firefox中的結果爲「是」

爲什麼會有差別?

回答

12

在條件語句中聲明函數是非標準的,所以不這樣做。這是一個已知的問題。您可以使用函數表達式來代替聲明:

var f; 
if(true) { 
    f = function() { alert("yes"); }; 
} else { 
    f = function() { alert("no"); }; 
} 
f(); 

famous Kangax article on function expressions給出了一些額外的細節:

FunctionDeclarations只允許出現在計劃函數體。句法上,他們不能出現在區塊({ ... }) - 例如if,whilefor陳述。這是因爲區塊只能包含報表而不是SourceElements,其中函數聲明是。

同一篇文章也說:

值得一提的是,按照規範,允許實現引進語法擴展(見第16條),但仍然是完全符合的。這正是目前這麼多客戶所發生的情況。其中一些將塊中的函數聲明解釋爲任何其他函數聲明 - 只需將它們提升到封閉範圍的頂部;其他 - 引入不同的語義並遵循稍微複雜的規則。

5

從V8(Chrome的JavaScript引擎)bug tracker

不是一個錯誤。 Firefox是唯一可以滿足你期望的瀏覽器。

Safari和IE在這方面的行爲與Chrome的/ V8相同。

2

發生這種情況是由於缺乏火狐功能提升的,如在ECMAScript的構思5.

Chrome中運行的功能的主體之前正確分配一個值到f(), 的F,從而第一個版本()被第二個覆蓋。

的SpiderMonkey(Firefox的JavaScript引擎)運行沒有assignin前值到f()的代碼,所以 它使用的道路上遇到的唯一值:function f() { alert("yes"); };

什麼功能提升?
JavaScript的函數範圍意味着函數中聲明的所有變量在整個函數體中都是可見的 。奇怪的是,這意味着變量在宣佈前甚至可以看到 。 JavaScript的這種功能非正式地稱爲提升: JavaScript代碼的行爲就像一個函數中的所有變量聲明(但不是任何 關聯的賦值)都被「懸掛」到該函數的頂部。

來源:
http://statichtml.com/2011/spidermonkey-function-hoisting.html
2011 - 奧賴利 - 的JavaScript - 權威指南第6版