js詞法作用域是由你在寫**時將變數和塊作用域寫在**來決定。
js動態作用域和this機制息息相關。它的作用域詩是在執行的過程中確定
var a = 1;
function foo()
foo(); // 1
從上面的**,我們可以看出:foo中列印a的值不是由寫**的位置確定的,而是取決於foo執行的位置。
最小授權原則
最小授權原則是指在軟體設計中,應該最小限度地暴露必要內容,而將其他內容都「隱藏」起來,比如某個模組或物件的 api 設計。這個原則可以延伸到如何選擇作用域來包含變數和函式。如果所有變數和函式都在全域性作 用域中,當然可以在所有的內部巢狀作用域中訪問到它們。但這樣會破壞前面提到的最小 特權原則,因為可能會暴漏過多的變數或函式,而這些變數或函式本應該是私有的,正確 的**應該是可以阻止對這些變數或函式進行訪問的。
例如:
function dosomething(a)
function dosomethingelse(a)
var b;
dosomething( 2 ); // 15
在這個**片段中,變數 b 和函式 dosomethingelse(..) 應該是 dosomething(..) 內部具體 實現的「私有」內容。給予外部作用域對 b 和 dosomethingelse(..) 的「訪問許可權」不僅 沒有必要,而且可能是「危險」的,因為它們可能被有意或無意地以非預期的方式使用, 從而導致超出了 dosomething(..) 的適用條件。更「合理」的設計會將這些私有的具體內容隱藏在 dosomething(..) 內部,
例如:
function dosomething(a)
var b;
b = a + dosomethingelse( a * 2 );
console.log( b * 3 );
}dosomething( 2 ); // 15
現在,b 和 dosomethingelse(..) 都無法從外部被訪問,而只能被 dosomething(..) 所控制。 功能性和最終效果都沒有受影響,但是設計上將具體內容私有化了,設計良好的軟體都會 依此進行實現。
規避衝突
當我們的程式**逐漸多起來,難免會出現變數衝突。那麼如何規避衝突就顯得額外重要。
函式可以把識別符號嚴謹的"隱藏"起來,外部無法訪問到,利用這個特性我們可以很好的規避衝突。
function foo()
function bar()
foo和bar中定義了相同的變數a,但是卻不會相互造成影響。因為函式可以很好的把識別符號"隱藏"起來。
變數衝突的乙個典型例子存在於全域性作用域中。當程式中載入了多個第三方庫時,如果它 們沒有妥善地將內部私有的函式或變數隱藏起來,就會很容易引發衝突。
這些庫通常會在全域性作用域中宣告乙個名字足夠獨特的變數,通常是乙個物件。這個物件 被用作庫的命名空間,所有需要暴露給外界的功能都會成為這個物件(命名空間)的屬 性,而不是將自己的識別符號暴漏在頂級的詞法作用域中。
例如:
var mylibrary =
}
立即執行函式(iife)
var a=2;
(function foo() )();
console.log( a ); // 2
函式名對 iife 當然不是必須的,iife 最常見的用法是使用乙個匿名函式表示式。雖然使 用具名函式的 iife 並不常見,但它具有以下優勢:
匿名函式在棧追蹤中不會顯示出有意義的函式名,使得除錯很困難。
如果沒有函式名,當函式需要引用自身時只能使用已經過期的arguments.callee引用, 比如在遞迴中。另乙個函式需要引用自身的例子,是在事件觸發後事件***需要解綁 自身。
匿名函式省略了對於**可讀性/可理解性很重要的函式名。乙個描述性的名稱可以讓 **不言自明。
因此具名函式的 iife 也是乙個值得推廣的實踐。
(function() ())
iife 也可以和其他形式的函式一樣實現引數的傳遞(多說一句:引數傳遞是按值傳遞)。
(function foo(a) )(3);
這個模式的另外乙個應用場景是解決 undefined 識別符號的預設值被錯誤覆蓋導致的異常(雖 然不常見)。將乙個引數命名為 undefined,但是在對應的位置不傳入任何值,這樣就可以 保證在**塊中 undefined 識別符號的值真的是 undefined:
undefined = true; // 給其他**挖了乙個大坑!絕對不要這樣做!
(function iife( undefined )
})();
iife 還有一種變化的用途是倒置**的執行順序,將需要執行的函式放在第二位,在 iife 執行之後當作引數傳遞進去。儘管這種模式略顯冗長,但有些人認為它更易理解。
var a=2;
(function iife( def ) )(function def( global ) );
詞法作用域 vs 動態作用域
scheme是一門採用詞法作用域 lexical scoping 的lisp方言,這個設計是從alogol語言裡借鑑過來的。現在,詞法作用域已經被許多lisp方言所吸收,實踐表明,這的確是一項正確的設計,避免了很多奇怪的錯誤,比較符合人類的思維習慣。但是,在某些場合下,動態作用域又是很有用的特性,比...
詞法作用域和動態作用域
作用域是指程式源 中定義變數的區域。它規定了如何查詢變數,也是就確定當前執行 對變數的訪問許可權。js 採用了詞法作用域 lexical scoping 也就是靜態作用域。js 採用的詞法作用域是靜態作用域,因此函式的作用域在函式定義的時候就決定了。與靜態作用域相對的是動態作用域,函式的作用域是在函...
詞法作用域
域表示的就是 範圍,即 作用範圍.就是乙個名字在什麼地方可以被使用,什麼時候不能使用.所謂的 詞法 作用域,就是 在編寫過程中體現出來的作用範圍.一旦寫好,不用執行,作用範圍就已經確定好了.這個就是所謂詞法作用域.這意味著函式執行在定義它的作用域中,而不是在呼叫它的作用域中。在 js 中詞法作用域規...