5 回答

TA貢獻1784條經驗 獲得超7個贊
不同之處在于它functionOne
是一個函數表達式,因此只在到達該行時定義,而是functionTwo
一個函數聲明,并且只要執行其周圍的函數或腳本(由于提升)就會定義。
例如,一個函數表達式:
// TypeError: functionOne is not a function
functionOne();
var functionOne = function() {
console.log("Hello!");
};
并且,一個函數聲明:
// Outputs: "Hello!"
functionTwo();
function functionTwo() {
console.log("Hello!");
}
這也意味著您無法使用函數聲明有條件地定義函數:
if (test) {
// Error or misbehavior
function functionThree() { doSomething(); }
}
上面的實際定義functionThree與... test的值無關 - 除非use strict有效,否則它只會引發錯誤。

TA貢獻1744條經驗 獲得超4個贊
說到全局上下文,var
語句和FunctionDeclaration
最后都將在全局對象上創建一個不可刪除的屬性,但兩者的值都可以被覆蓋。
兩種方式之間的細微差別在于,當變量實例化過程運行時(在實際代碼執行之前),所有聲明的標識符var
都將被初始化undefined
,并且FunctionDeclaration
自那時起使用的標識符將可用,例如:
alert(typeof foo); // 'function', it's already available
alert(typeof bar); // 'undefined'
function foo () {}
var bar = function () {};
alert(typeof bar); // 'function'
分配bar FunctionExpression發生在運行時間。
由a創建的全局屬性FunctionDeclaration可以像變量值一樣被覆蓋而沒有任何問題,例如:
function test () {}
test = null;
您的兩個示例之間的另一個明顯區別是第一個函數沒有名稱,但第二個函數有它,這在調試(即檢查調用堆棧)時非常有用。
關于您編輯的第一個示例(foo = function() { alert('hello!'); };),這是一個未聲明的作業,我強烈建議您始終使用該var關鍵字。
使用賦值,如果沒有var
語句,如果在作用域鏈中找不到引用的標識符,它將成為全局對象的可刪除屬性。
此外,未聲明的作業ReferenceError
在嚴格模式下投入ECMAScript 5 。
必讀:

TA貢獻1796條經驗 獲得超4個贊
您在那里發布的兩個代碼段幾乎在所有目的下都會以相同的方式運行。
但是,行為的差異在于使用第一個variant(var functionOne = function() {}
),該函數只能在代碼中的該點之后調用。
使用第二個variant(function functionTwo()
),該函數可用于在聲明函數的上方運行的代碼。
這是因為對于第一個變體,函數foo
在運行時分配給變量。在第二個中,foo
在解析時將該函數分配給該標識符。
更多技術信息
JavaScript有三種定義函數的方法。
您的第一個代碼段顯示了一個函數表達式。這涉及使用“function”運算符來創建函數 - 該運算符的結果可以存儲在任何變量或對象屬性中。函數表達式就是這樣強大的。函數表達式通常稱為“匿名函數”,因為它不必具有名稱,
你的第二個例子是函數聲明。這使用“function”語句來創建函數。該函數在分析時可用,并且可以在該范圍內的任何位置調用。您以后仍可以將其存儲在變量或對象屬性中。
定義函數的第三種方法是“Function()”構造函數,它在原始帖子中沒有顯示。不建議使用它,因為它的工作方式與
eval()
存在問題的方式相同。
添加回答
舉報