2008-11-04 88 views
135

此代碼始終工作,甚至在不同的瀏覽器:爲什麼我在JavaScript中定義函數之前可以使用它?

function fooCheck() { 
    alert(internalFoo()); // We are using internalFoo() here... 

    return internalFoo(); // And here, even though it has not been defined... 

    function internalFoo() { return true; } //...until here! 
} 

fooCheck(); 

我找不到一處提到爲什麼它應該工作,雖然。 我第一次在John Resig的演示文稿中看到了這一點,但它只是被提及。對於這件事,沒有任何解釋。

有人請賜教嗎?

+2

在Firefox的新版本,如果代碼是在一個try/catch這不起作用。看到這個小提琴:http://jsfiddle.net/qzzc1evt/ – 2015-01-30 22:11:01

回答

182

function聲明是神奇的,並導致其標識符在其代碼塊*中的任何內容被執行之前被綁定。

這與具有function表達式的分配不同,該表達式按照正常的自頂向下順序進行評估。

如果更改了例子說:

var internalFoo = function() { return true; }; 

它會停止工作。

函數聲明在語法上與函數表達式完全分離,即使它們看起來幾乎相同並且在某些情況下可能不明確。

這記錄在ECMAScript standard,部分10.1.3。不幸的是,ECMA-262即使是標準標準也不是一個非常易讀的文件!

*:包含功能,塊,模塊或腳本。

2

有些語言有標識必須在使用前要定義的要求。原因是編譯器在源代碼上使用單個傳遞。

但是,如果有多個通行證(或一些支票被推遲),你可以完美地生活沒有這個要求。 在這種情況下,代碼可能會先讀取(並解釋),然後設置鏈接。

0

函數「internalFoo」的主體需要在解析時去某處,所以當JS解釋器讀取代碼(又名解析)時,函數的數據結構被創建並且名稱被分配。

只是到了後來,則代碼運行,JavaScript的實際上是嘗試找出是否「internalFoo」存在,它是什麼,它是否可以被稱爲等

13

瀏覽器讀取從開始你的HTML結束並且可以在讀取它時執行它並將其解析爲可執行塊(變量聲明,函數定義等)。但是在任何時候,只能使用html之前定義的內容。

這與處理(編譯)所有源代碼,將其與任何需要的庫鏈接在一起並構建可執行模塊的其他編程上下文不同,此時執行開始。

您可以定義引用項目(變量,其他函數等)的函數,這些函數會沿着它們進一步定義,但在所有塊都可用之前,您無法執行這些函數。

隨着您熟悉JavaScript,您將會深刻地意識到您需要按正確的順序編寫內容。

修訂:爲確認接受的答案(上述),使用Firebug來瀏覽網頁的腳本部分。在實際執行任何代碼之前,您會看到它從函數跳到函數,僅訪問第一行。

+4

+1在你的答案結尾修訂,這是必不可少的部分。 – hippietrail 2012-10-24 16:27:02

-4

出於同樣的原因,下面將始終把foo在全局命名空間:

if (test condition) { 
    var foo; 
} 
4

這就是所謂的起重 - 調用(稱)已確定,其中前一個功能。

兩種不同類型的功能,我想寫有:

表達式函數&減速功能

  1. 表達式函數:

    函數表達式可以被存儲在一個變量中,以便他們不需要函數名稱。他們也將被命名爲匿名函數(一個沒有名字的函數)。

    要調用(調用)它們總是需要使用變量名稱。如果在定義的地方進行調用,這意味着這裏沒有發生吊裝,這些類型的功能將不起作用。我們總是必須先定義表達式函數然後調用它。

    let lastName = function (family) { 
    console.log("My last name is " + family); 
    }; 
    let x = lastName("Lopez"); 
    

    這是你如何能在ECMAScript中  6寫:

    lastName = (family) => console.log("My last name is " + family); 
    
    x = lastName("Lopez"); 
    
  2. 減速功能:

    函數聲明的語法如下不立即執行。它們被「保存以供以後使用」,並且將在稍後被調用(被調用)時被執行。如果您在之前或之後將它們稱爲它們,則這些類型的函數將起作用。如果在定義之前調用減速功能 - 起升 - 正常工作。

    function Name(name) { 
        console.log("My cat's name is " + name); 
    } 
    Name("Chloe"); 
    

    吊裝例如:

    Name("Chloe"); 
    function Name(name) { 
        console.log("My cat's name is " + name); 
    } 
    
相關問題