雖然《JavaScript權威指南》這本書很好,可是有一些東西讓人容易理解錯。最近在惡補基礎,結合這本書,我想把變量的做用域從新梳理一下:java
"一個變量的做用域(scope)是程序源代碼中定義這個變量的區域。全局變量擁有全局做用域,在JavaScript代碼中的任何地方都是有定義的。然而在函數內聲明的變量只在函數體內有定義。"----摘自《JavaScript權威指南》第6版es6
"在一些相似C語言的編程語言中,花括號內的每一段代碼都具備各自的做用域,並且變量在聲明他們的代碼段以外是不可見的,咱們稱之爲塊級做用域。"----摘自《JavaScript權威指南》第6版編程
在ECMAScript 6以前是沒有塊級做用域的,這裏說的是ECMAScript5.1規範標準。閉包
變量分全局變量,局部變量。這就決定了變量的做用域:全局做用域、與函數做用域編程語言
demo1:函數
var scope = "global"; //聲明一個全局變量 function check() { var scope = "local"; //聲明一個同名的局部變量 return scope; //返回局部變量的值,而不是全局變量的值 } check(); => "local"
解:spa
" 在函數體內,局部變量的優先級高於同名的全局變量。若是在函數內聲明的一個局部變量or函數參數中帶有的變量和全局變量重名,那麼全局變量就會被局部變量所遮蓋。"----摘自《JavaScript權威指南》第6版code
實踐證實:orm
var scope = "global"; //聲明一個全局變量 function check() { var scope = "local"; //聲明一個同名的局部變量 return scope; //返回局部變量的值,而不是全局變量的值 } check(); => "local" console.log(scope); =>"blobal"
書上的話容易誤導人,不少人一開始把這裏的"遮蓋"當成了覆蓋,想固然認爲全局變量scope的值變成了"local",實則否則。 在函數體內,局部變量的優先級高於同名的全局變量。其實check函數返回就是局部變量scope,而不是全局變scope;二者只是同名而已。
對象
demo2:
scope = "global"; //聲明一個全局變量,不使用var聲明 function t() { scope = "local"; //修改了全局變量 myscope = "local; //聲明一個新的全局變量 return [scope,myscope]; //返回兩個值 } t(); scope => "local" myscope => "local" //二者都爲 "local"
解:
在js中,若是給一個沒有聲明的變量賦值,都是全局變量,並且是全局對象的屬性。
demo3:
var scope="global"; //聲明一個全局變量 function t(){ console.log(scope); var scope="local" console.log(scope); } t(); scope => 第一次爲 undefined 第二次才爲 "local"
解:
不少人勿認爲第一次打印的是全局變量,其實否則。 js函數做用域:指在函數內聲明的全部變量在函數體內始終是可見的。有意思的是,這意味着變量在聲明以前甚至已經可用。js這個特性被非正式地成爲聲明提早。即:js函數裏聲明的全部變量都(不涉及賦值)被「提早」到函數體的頂部。
上述過程等價:將函數內的變量聲明「提早」至函數體頂部,變量初始化留在原來的位置。等價於以下的代碼:
var scope="global"; //聲明一個全局變量 function t(){ var scope; //頂部聲明瞭局部變量 console.log(scope); //變量存在,但未初始化 scope="local" //初始化並賦值 console.log(scope); } t();
函數內聲明的變量都是局部變量,函數外是沒法訪問的,外部想要訪問函數內的變量能夠採用閉包來實現,代碼實例以下:
demo4:
function t (){ var x=10; return function () { return x; } } console.log(x); //報錯,x未定義 var a = t(); console.log(a()); //10
在js編寫當中,因爲規範太少,寫法靈活,可能致使出現各類bug。聲明變量時,最好放在函數體頂部,增長易讀性。
es6中,增長了不少特性,js的規範愈來愈標準化,已成爲一門通吃各個平臺的語言,加油!