變量所在的上下文,指的是變量在哪些地方能夠訪問前端
對於JavaScript來講有全局做用域可是沒有塊級做用域,在ES6中引入了關鍵字let能夠生成塊做用域.見如下代碼:後端
var value = true if (value) { var age = 18 console.log(`我今年${age}歲了`) } console.log (`我也是${age}歲了哦`) //輸出 "我今年18歲了" "我也是18歲了哦" // 可見在if()中不存在塊級做用域
在這裏if()裏的變量具備全局做用域,全局皆可以使用函數
var value = true if (value) { let age = 18 console.log(`我今年${age}歲了`) } console.log (`我也是${age}歲了哦`) /*輸出 "我今年18歲了" "error" "ReferenceError: age is not defined*/
在這裏使用關鍵字let 使 if () 塊裏的變量age產生了塊級做用域,使得它只在這個塊裏生效.學習
JS中有函數做用域,指的是做用域在函數內部。這裏一共說了三種做用域,其實能夠說是兩種:一種是全局做用域,而是局部做用域(函數做用域、塊級做用域),塊級做用域概念又包括了函數做用域。code
var a = "你好,我是a"; function scopeChain(a) { var b =1; function inScope(a) { var c = "螞蟻" console.log(`大象愛${c}`) console.log(`我是最內層的函數,這裏也可使用a: ${a}`) } console.log(`能使用a嗎?${a}`) inScope(a) } scopeChain(a)
這裏a是全局做用域下的變量,b是函數scopeChain()做用域下的變量,而c是函數scopeChain()裏的inScope()函數做用域下的變量。對象
做用域鏈的前端始終是當前環境做用域下變量對象,逐層往外做用域連接,最後端是全局變量環境下的變量,這些變量時連接在一塊兒,在解析一個變量時從鏈前端日後端搜索(從內不找外部找),可是有一點值得注意:每一個變量的做用域老是從自身聲明的做用域往外找,而不是調用它的地方 :ip
var a = 1 function fn1(){ function fn3(){ var a = 4 fn2() } var a = 2 return fn3 } function fn2(){ console.log(a) } var fn = fn1() fn() //輸出1
這裏就是當fn1() 執行後調用 fn2() 時,發現fn3()做用域下沒有,也就是做用域鏈前端沒有,往外找一層也就是fn1()做用域下進行查找,做用域也就日後端前進了一步,發現仍是沒有,繼續往外層做用域查找找到了全局做用域,也就是做用域鏈的最後端,找到了後調用它。作用域
可是對於fn2()來講它須要調用a這個變量,這裏也就出現了誤區:在fn3()裏有變量a,那麼是用的是這個變量a嗎?io
var a =1
因此調用它並輸出a時也就等於1.var a = 1 function fn1(){ function fn2(){ console.log(a) } function fn3(){ var a = 4 fn2() } var a = 2 return fn3 } var fn = fn1() fn() //輸出多少?
return fn3
,也就調用了fn3(),而後fn3()裏又是調用fn2(),而fn() 是在fn1()裏聲明的,天然也就使用了fn1()裏的變量a,又由於a變量在調用前聲明並賦值了,故此輸出爲2 var a = 1 function fn1(){ function fn3(){ function fn2(){ console.log(a) } var a fn2() a = 4 } var a = 2 return fn3 } var fn = fn1() fn() //輸出多少?
分析這段代碼,發現與上面代碼不一樣之處在於先聲明瞭 ` var a
後沒有裏脊賦值,在調用了fn2()後再進行的賦值,那麼這裏應該是多少呢?console
var a
時,也就是執行到了fn3()代碼前,函數聲明和變量聲明會提早至代碼前端,因此這裏聲明並無影響到輸出值得改變,可是賦值操做是按照程序順序執行的,當調用前,a只聲明沒有賦值,則會輸出undefined。 而具體變量查找是符合做用域鏈的順序來的.總結以下:
我的學習備忘,若有謬誤,歡迎指正。