塊級作用域與函式作用域
阿新 • • 發佈:2019-01-31
函式作用域:變數在定義的環境中以及巢狀的子函式中處處可見;
塊級作用域:變數在離開定義的塊級程式碼後立即被回收。
函式作用域
在ES6之前,js的作用域只有兩種:函式作用域和全域性作用域。使用var宣告的變數,都存在變數提升的過程。
console.log(a); //undefined
console.log(c); //undefined
console.log(d); //function d() {}
console.log(b); //報錯,b is not defined
var a = 0;
let b = 1;
var c = function () {
};
function d() {
}
由此可見使用let宣告的變數不會提升,函式宣告會完全提升。上面的程式碼等價於:
var a;
var c;
function d() {}
console.log(a);
console.log(c);
console.log(d);
console.log(b);
a = 0;
let b = 1;
c = function () {
};
塊級作用域
ES6中定義了塊級作用域,使用let宣告的變數只能在塊級作用域裡訪問,有“暫時性死區”的特性(也就是說宣告前不可用)。
'use strict';
var test = 1;
function func(){
//列印test的值
console.log(test); //報錯, test is not defined.
let test = 2;
};
func();
函式會從自身的活動物件開始,一層層向上尋找自己所需的變數,該函式在尋找test時發現,自己的作用域裡聲明瞭let,它就不會再往上找,而let在宣告之前是不可用的,所以就會報錯。
自己的理解
雖然《js高程》裡說,ES6之前,js沒有塊級作用域。但我認為with語句和try-catch語句有類似於塊級作用域的地方。
var l = {
x: 0,
y: 1
};
function f() {
with(l) {
console.log(x); //0
var a = 1;
}
cosnole.log(a); //1
console.log(x); //報錯,x is not defined.
}
f();
函式f利用with語句擴充套件了自己的作用域鏈,相當於with語句開始執行時,引數l中所包含的所有變數都被臨時加入到該函式的活動物件中,等到語句執行結束,它們就會被移除。它們只在with語句塊中有效。還有一點就是,with語句中宣告的變數a,使用var宣告的變數會自動被新增到離它最近的環境中,離a最近的環境就是函式的區域性環境,所以a就會被新增到函式的活動物件中,即使在with語句之外也能被訪問。