2014-10-10 51 views
0

我有兩個函數命名初始化的Javascript:在函數聲明函數表達式

一個使用函數聲明和其他使用函數表達式聲明,如下所示:

function init() { 
    alert ('init 1'); 
} 

var init = function(){ 
    alert('init 2'); 
} 

init(); 

當我調用init函數它提醒初始化2.

Demo

我questio n是:

1-爲什麼javascript不會拋出錯誤,因爲這兩個函數具有相同的名稱。

2-如何調用第一個函數?

+0

第二個init不是一個函數,第一個是通過一個簡單的語句調用的,例如'init();'http://stackoverflow.com/questions/336859/var-functionname-function-vs-function-函數名稱 – VPK 2014-10-10 11:56:06

+0

init();不是第一個調用第二個方法,請檢查我的小提琴。 – 2014-10-10 11:57:39

回答

3

爲什麼javascript不會拋出錯誤,因爲兩個函數都有相同的名稱。

它們沒有相同的名稱。第二個是包含匿名函數的變量init。第一個是名爲init的函數。

您可以通過執行兩個以下測試:

console.log(init.name); 

你會看到,第一確實有一個名字init,而第二個沒有名字。

我該如何調用第一個函數?

在這個例子中,在第二個變量中使用init後,第一個不能被調用。除非你有另外一個引用,像這樣:

function init() { 
     alert ('init 1'); 
} 
var original = init; 
+1

雖然學生們可能希望在命名函數和賦予命名變量的匿名函數之間作出區分,並且兩者之間確實存在差異,但在日常實踐中,簡單的事實就是兩種名稱共享本地作用域,並且不能同時存在同一個名稱。 OP的問題僅僅是爲什麼JS沒有像其他語言那樣報告這個錯誤(回答:因爲它沒有),並且一旦我在本地範圍內覆蓋了一個名稱,我可以返回舊版本(答案:你不能)。 – 2014-10-10 12:08:28

+0

*它們不具有相同的名稱*實際上,這是** NOT ** JS不會拋出錯誤的原因。如果是這樣的話,可能會認爲'function foo(){}函數foo(){}'或'var x = 1; var x = 1; ** **會拋出一個錯誤,但他們也不會。 JS不拋出錯誤的原因是,好的,** JS在變量或函數重定義或重新分配的情況下不會拋出錯誤**。無論是變量還是函數都是無關緊要的。 – 2014-10-10 12:18:55

0

Javascript獲取函數的最後定義。 您可以將其重命名爲唯一的,也可以使用「嚴格」來使其具有本地功能。

function functions(){ 
    "use strict" 
    var init = function(){ 
     console.log("b"); 
    }; 

    return { 
     start : init 
    } 
}; 

var fn = new functions(); 
fn.start(); 
+0

沒有得到關於「嚴格使用';使其成爲本地函數」的部分。 – 2014-10-10 12:02:04

2

沒有什麼之間你正在做什麼和

var i = 1; 
var i = 2; 

沒有,JS不會拋出一個錯誤,也沒有,一旦你重新定義i你不能老根本不同價值迴歸。

在ES6和一些現代的瀏覽器,你可以說

const i = 1; 

,然後如果它重新定義了引擎會抱怨。

+0

所以簡單地說,變量init就是重寫第一個init函數? – 2014-10-10 12:07:58

+0

是的,雖然不是「覆蓋」,我可能會說「覆蓋」或「重新定義」或「重新分配」。 – 2014-10-10 12:10:13

2

JavaScript中的聲明被掛起。函數聲明是聲明的一種類型。因此,你的程序是等價於:

var init = function init() { 
 
    alert("init 1"); 
 
}; 
 

 
var init = function() { 
 
    alert("init 2"); 
 
}; 
 

 
init();

如果你的第二個定義之前調用init那麼它會提醒init 1

function init() { 
 
    alert("init 1"); 
 
} 
 

 
init(); 
 

 
var init = function() { 
 
    alert("init 2"); 
 
};

由於吊裝你甚至可以校準升init它出現在程序之前:

init(); 
 

 
function init() { 
 
    alert("init 1"); 
 
} 
 

 
var init = function() { 
 
    alert("init 2"); 
 
};

只記得比他們在程序中出現什麼樣的順序不管,函數的聲明永遠是第一位:

init(); 
 

 
var init = function() { 
 
    alert("init 2"); 
 
}; 
 

 
function init() { 
 
    alert("init 1"); 
 
}

Hop e有幫助。

+0

懸掛的絕佳摘要,但它與OP的問題有什麼關係? – 2014-10-10 12:03:32

+1

我知道關於提升,我想知道我的第一個函數會發生什麼,它是否被第二個函數覆蓋或者它是否仍然存在於全局名稱空間中? – 2014-10-10 12:10:37

0

您可以種命名空間:

var p1 = { 
 
    init: function() { 
 
    alert('init 1'); 
 
    } 
 
}; 
 

 
var p2 = { 
 
    init: function() { 
 
    alert('init 2'); 
 
    } 
 
}; 
 

 
var init = function() { 
 
    p1.init(); 
 
    p2.init(); 
 
}; 
 

 
init();
Running ...

0

這工作:

function init() { 
    alert ('init 1'); 
} 

var init = (function(oldInit) { return function() { 
    oldInit(); // Call the first definition this way 
    alert('init 2'); 
}; })(init); 

init(); 

關鍵是要有第二的init()還記得以前的初始化。 Javascript不會拋出錯誤,因爲重新定義函數通常很有用。