一.JS變量提升
1.當瀏覽器引擎解析js代碼時,將js中的所有一開始就是var聲明的和function聲明的都提升到全局。此時又叫全局作用域
1 console.log(aa); 2 console.log(ff); 3 console.log(bb); 4 5 var aa = "aa"; 6 7 function ff(){ 8 console.log("ff"); 9 }
注意:undefined和is not defined是不一樣的。
-
undefined:聲明了該變量但是調用時沒有定義值
-
is not defined:沒有聲明也沒有定義值
2.對於函數也一樣,又叫做局部作用域
1 function ff(){ 2 3 console.log(aa); 4 console.log(fun); 5 console.log(bb); 6 var aa = "aa"; 7 function fun(){} 8 9 } 10 11 ff();
3.作用域分類
-
全局作用域
-
函數作用域
-
塊作用域(ES6才有)
注:查找作用域先從當前作用域查找再找上層作用域
例1:
1 var x = 10; 2 function fn() { 3 console.log(x); 4 } 5 function show(f) { 6 var x = 20; 7 f(); 8 } 9 show(fn); //10
分析:
- 全局作用域
- var x
- function fn
- function show
- 函數作用域fn
- 函數作用域show
- var x
注意此處兩個函數作用域是同一級的
執行到console.log(x)時,會先看fn()的函數作用域內是否有x變量沒有就出去看全局的(由於show和fn為同一級所以不會看show),則此時x = 10;
例2:
1 var fn = function () { 2 console.log(fn) 3 } 4 fn() 5 6 var obj = { 7 fn2: function () { 8 console.log(fn2) 9 } 10 } 11 obj.fn2()
分析:
- 全局作用域:
- var fn
- var obj
- 全局中無函數作用域
第一個fn():會執行console.log(fn)在函數中沒有fn,找全局發現fn變量是一個函數則返回函數
第二個obj.fn2():會執行console.log(fn2)在函數中沒有發現fn2,不回去找obj對象中的fn2由於沒有對象作用域這個東西,則找全局也沒有找到報錯了。
如果稍微修改以下將fn2改為this.fn2則不會報錯,綁定調用對象obj然后調用obj的fn2。
1 var fn = function () { 2 console.log(fn) 3 } 4 fn() 5 6 var obj = { 7 fn2: function () { 8 console.log(this.fn2) 9 } 10 } 11 obj.fn2()
4.上下文棧
由於和其他語言的壓棧方式相同則不在贅述