簡體   English   中英

Javascript中的模糊函數聲明

[英]Ambiguous function declaration in Javascript

我是Javascript的新手,並對函數聲明的工作方式感到困惑。 我對此做了一些測試並獲得了一些有趣的結果:

say();

function say()
{
    alert("say");
}

前進聲明工作和彈出“說”

相反

say();

say = function()
{
    alert("say");
}

沒有工作,雖然它也聲明了一個函數對象

如果我們聲明該函數並在之后重新聲明:

function say()
{
    alert("speak");
}

say();

function say()
{
    alert("say");
}

我得到“說”而不是“說話”。 這太令人驚訝了!

好。 似乎只有最新的函數聲明才有效。 然后讓我們首先聲明函數對象,然后是“常規”函數:

say = function()
{
    alert("speak");
}

say();

function say()
{
    alert("say");
}

say();

另一個驚喜,是“說話”,然后是“說話”。 “常規”功能聲明根本不起作用!

是否有所有這些的解釋? 並且,如果“常規”函數聲明真的是“脆弱的”並且可以通過具有相同名稱的函數對象輕松覆蓋,那么我應該遠離它嗎?

另一個問題是:只使用函數對象格式,前向聲明是否變得不可能? 有沒有辦法在Javascript中“模擬”它?

Javascript的工作方式如下:

解析文檔,並在執行實際語句之前立即考慮function聲明。 這解釋了你的第一個例子。

如果將函數分配給局部變量,則在執行期間完成,因此您無法在第二個示例中使用該方法。

您所經歷的是,如果您聲明一個函數兩次,則最后一個函數將由整個應用程序使用。 那是你的第三個例子。

這些函數是window對象的成員,它們實際上是全局聲明的。 如果將局部變量分配給函數的值,則該局部變量優先於window對象中的成員。 如果javascript找不到局部變量,它會在范圍內搜索以找到它, window對象是最后的手段。 這是您的最后一個例子發生了什么,它有一個可變的say是在一個更具體的范圍比全局函數say

如果你想重新聲明say在運行時,即在交換你的最后一個例子聲明的順序,那么你會看到你所期望的兩種不同的警報:

say(); //speak, the global function

function say() {
  alert('speak');
}

var say = function() {
  alert('say');
}

say(); //say, the declared local variable
say();

function say()
{
    alert("say");
}

這里解釋器在調用時獲取say()的定義並執行它。

say();

say = function()
{
    alert("say");
}

這里沒有定義say()來獲取 - 而是將一個匿名函數賦給變量。 解釋器無法“找到”它,就像它可以找到前向聲明一樣。

function say()
{
    alert("speak");
}

say();

function say()
{
    alert("say");
}

這里say定義然后重新定義 - 最后一個定義勝出。

say = function()
{
    alert("speak");
}

say();

function say()
{
    alert("say");
}

say();

這里say是一個指向匿名函數的變量(在解釋第一個語句之后)。 這優先於任何函數定義,就像在賦值之前放置函數定義一樣。

但如果你有

say();

say = function()
{
    alert("speak");
}

say();

function say()
{
    alert("say");
}

然后你會得到“說”然后“說”。

您可以期望按順序應用函數定義。 然后將按順序執行所有非方法代碼行,包括函數對象的賦值。 這解釋了您的每個示例。 這是一個有趣的問題。 嘗試調用它之后,你真的無法分配一個函數對象,並期望它能夠工作。 但是,實際上將首先應用遵循可執行代碼的函數定義。

它總是好主意稍后調用該函數,即使javascript的工作方式如此。

大多數語言不會以這種方式工作,而是這樣做。

function say(){
    alert("say");
}

say();

要么

say = function(){
    alert("say");
}

say();

要么

(function(){
    alert("say");
})();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM