作用域:
作用域有兩種,一種是全局作用域,對應全局變量;另一種是局部作用域,對應的是局部變量。
最外層函數定義的變量擁有全局作用域,對任何內部函數來說,都是可以訪問的。
局部作用域一般只在固定的代碼片段內可以訪問,函數外部是訪問不到的。
閉包有權訪問另一個函數作用於中的變量,在閉包函數執行時,會將它的外部函數的對象添加到它的作用域中。
ES6之前沒有塊級作用域,JavaScript的作用域是相對函數而言的。
C++:
for(int i=0;i<5;i++){
//i的作用範圍只在這個for循環裏面
}
printf("%d",&i); //error
JavaScript:
for(var i=0;i<5;i++){
}
console.log(i); //5
ES6增加了塊級作用域,用let聲明。
作用域鏈:
執行環境定義了變量或者函數有權訪問的其他數據,決定了它們各自的行爲,每個執行環境都有一個與之關聯的變量對象。當代碼在一個執行環境中執行時,會創建變量對象的作用域鏈,作用域鏈是保證對執行環境有權訪問的所有變量和函數的有序訪問。作用域鏈的前端,始終都是當前執行的代碼所在環境的變量對象。
Tips:
- 標識符解析是沿着作用域鏈一級一級地搜索標識符的過程。
- 內部環境可以通過作用域鏈訪問到所有的外部環境,但是外部環境不能訪問內部環境的任何變量和函數。
作用域鏈的示例如下:(參考JavaScript高級程序設計)
var color = "blue";
function changeColor(){
var anotherColor="red";
function swapColor(){
var tempColor=anotherColor;
anotherColor=color;
color=tempColor;
//這裏可以訪問color, tempColor, anotherColor.
}
swapColor();
//這裏可以訪問color和anothColor;但是不能訪問tempColor。
}
changeColor();
//這裏只能訪問color
用圖的形式表示以上代碼的作用域:
延長作用域鏈:
有些語句可以在作用域鏈的前端臨時增加一個變量對象,該變量對象會在代碼執行後被移除,當執行流進入下列任何一個語句時,作用域鏈就會加長。
- try-catch語句中的catch塊;
- with語句。