[英]JavaScript function order: why does it matter?
當我的 JavaScript 調用一個定義在頁面下方而不是調用它的函數時, JSHint 會抱怨。 但是,我的頁面是用於游戲的,在下載整個內容之前不會調用任何函數。 那么為什么訂單函數會出現在我的代碼中呢?
http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
我在里面呻吟。 看起來我需要再花一天時間重新排序 6000 行代碼。 使用 javascript 的學習曲線一點也不陡峭,但它非常棒。
tl;dr如果你在一切加載之前都不打電話,你應該沒問題。
編輯:有關還涵蓋一些 ES6 聲明( let
、 const
)的概述: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet
這種奇怪的行為取決於
這里有一些例子。
bar(); //This won't throw an error
function bar() {}
foo(); //This will throw an error
var foo = function() {}
bar();
function bar() {
foo(); //This will throw an error
}
var foo = function() {}
bar();
function bar() {
foo(); //This _won't_ throw an error
}
function foo() {}
function bar() {
foo(); //no error
}
var foo = function() {}
bar();
這是因為所謂的提升!
定義函數有兩種方式:函數聲明和函數表達式。 區別很煩人而且很細微,所以讓我們說這有點錯誤:如果你像function name() {}
一樣寫它,它是一個聲明,當你像var name = function() {}
(或分配給返回的匿名函數,諸如此類),它是一個函數表達式。
var foo = 42;
//the interpreter turns it into this:
var foo;
foo = 42;
var foo = 42;
function bar() {}
//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;
var
語句將foo
的創建“拋出”到最頂部,但尚未為其分配值。 函數聲明緊隨其后,最后為foo
分配了一個值。
bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;
只有foo
的聲明被移到頂部。 分配僅在調用bar
之后出現,在所有提升發生之前。
bar();
function bar() {}
//turns to
function bar() {}
bar();
var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();
就像普通變量一樣,首先在作用域的最高點聲明foo
,然后給它賦值。
bar();
function bar() {
foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
foo();
}
bar();
foo = function() {}
正如我們之前看到的,只有foo
的創建被提升,賦值出現在它出現在“原始”(未提升)代碼中的地方。 當bar
被調用時,它是在foo
被賦值之前,所以foo === undefined
。 現在在bar
的函數體中,就好像您在執行undefined()
,這會引發錯誤。
主要原因可能是 JSLint 只對文件執行一次傳遞,因此它不知道您將定義這樣的函數。
如果您使用了函數語句語法
function foo(){ ... }
實際上在聲明函數的地方沒有任何區別(它總是表現得好像聲明在開頭)。
另一方面,如果您的函數設置為常規變量
var foo = function() { ... };
您必須保證在初始化之前不會調用它(這實際上可能是錯誤的來源)。
由於重新排序大量代碼很復雜,並且本身可能是錯誤的來源,我建議您尋找一種解決方法。 我很確定你可以事先告訴 JSLint 全局變量的名稱,這樣它就不會抱怨未聲明的東西。
對文件的開頭發表評論
/*globals foo1 foo2 foo3*/
或者您可以在那里使用文本框。 (我也認為你可以在參數中將它傳遞給內部 jslint 函數,如果你能插手的話。)
有太多人在推行關於 JavaScript 應該如何編寫的任意規則。 大多數規則是徹頭徹尾的垃圾。
函數提升是 JavaScript 的一個特性,因為它是一個好主意。
當您有一個內部函數通常是內部函數的效用時,將它添加到外部函數的開頭是一種可以接受的編寫代碼的風格,但它確實有一個缺點,即您必須通讀細節才能得到什么外部函數確實如此。
您應該在整個代碼庫中堅持一個原則,要么將私有函數放在模塊或函數中,要么放在最前面,要么放在最后。 JSHint 有利於增強一致性,但您應該絕對調整 .jshintrc 以滿足您的需要,而不是將您的源代碼調整為其他人古怪的編碼概念。
您可能會在野外看到的一種編碼風格應該避免,因為它沒有任何優勢,只會給您帶來重構的痛苦:
function bigProcess() {
var step1,step2;
step1();
step2();
step1 = function() {...};
step2 = function() {...};
}
這正是函數提升要避免的。 只需學習語言並發揮其優勢即可。
只有函數聲明被提升,而不是函數表達式(賦值)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.