不管如何,函數是惟一擁有自身做用域的結構,其它任何形式的結構都不支持做用域。代碼以下所示javascript
var demo = function () { ... };
或java
function demo () { ... };
JavaScript語言中沒有顯式命名空間定義,這意味着全部對象都定義在一個全局共享的命名空間下模塊化
引用變量時,向上依次遍歷當前做用域、全局做用域,直到發現該變量函數
在函數的自身做用域內,如變量聲明不使用var表達式,就會致使隱式全局變量產生。先看以下代碼所示對象
var demo = function () { number = 1; }; demo();
或blog
var demo = function () { for (number = 0; number < 5; number ++) { ... }; }; demo();
運行結果都爲聲明瞭一個全局變量number;如不想聲明或者覆蓋一個全局做用域內的同名變量,就必須使用var表達式。代碼以下所示ip
var demo = function () { var number = 1; }; demo();
或作用域
var demo = function () { for (var number = 0; number < 5; number ++) { ... }; }; demo();
運行結果都爲聲明瞭一個僅在當前做用域內纔有效的局部變量numberio
變量聲明在JavaScript語言中會被提高,這意味着var表達式、function聲明會被提高至當前做用域頂部。先看以下代碼所示console
demo(); var demo = function () { ... };
或
demo(); function demo () { ... };
代碼執行以前被轉化爲
var demo; demo(); demo = function () { ... };
或
function demo () { ... }; demo();
運行結果爲第一段代碼執行失敗,第二段代碼執行成功;由於第一段代碼執行時demo僅僅是聲明瞭,可是依然缺省值爲undefined
很是有意思的是局部變量聲明的提高。再看以下代碼所示
var number = 0; var demo = function () { if (true) { number = 1; } else { var number = 2; }; console.log(number); }; demo(); console.log(number);
代碼執行以前被轉化爲
var number, demo; number = 0; demo = function () { var number; if (true) { number = 1; } else { number = 2; }; console.log(number); }; demo(); console.log(number);
輸出結果爲一、0;本該覆蓋全局變量number的代碼轉爲聲明瞭一個局部變量number,如想覆蓋全局變量number,就必須取消全部的var表達式。代碼以下所示
var number = 0; var demo = function () { if (true) { number = 1; } else { number = 2; }; console.log(number); }; demo(); console.log(number);
輸出結果爲一、1
只有一個全局做用域會致使命名衝突,解決方案是匿名包裝器,做用是經過匿名函數建立一個新的命名空間。先看以下代碼所示
(function (){ ... })();
因爲匿名函數被認爲是表達式,爲了可調用性,須要先行執行,咱們能夠把自執行的匿名函數理解爲匿名包裝器。再看以下代碼所示
( //小括號內函數先行執行 function () { ... } ) //返回函數對象 (); //當即執行匿名函數,並調用以上執行結果即函數對象
經過匿名包裝器建立命名空間,不只能夠防止命名衝突,並且有利於程序的模塊化
還有一些其餘的函數表達式調用方法。代碼以下所示
+function (){ ... }(); !function (){ ... }(); (function (){ ... }());
var number = 0; (function (){ console.log(number); //猜猜輸出是什麼 var number = 1; })();