var 與let/const 變數提升與TDZ
阿新 • • 發佈:2018-11-08
我們都知道,在ES5及以前,var關鍵字被用來定義變數,但是到了ES6,就開始使用let/const來定義變數或者常量。那麼這兩者到底有什麼區別呢?
- var遵循函式作用域,let/const遵循塊級作用域;
- 由於變數提升,var關鍵字定義的變數在申明之前可以訪問,但得到undefined, let/const關鍵字定義的變數在申明之前訪問會丟擲ReferenceError的錯誤。
第一點沒什麼可講的,作用域不同而已。下面主要來談談第二點。那麼為什麼 let/const關鍵字定義的變數在申明之前不能被訪問呢,它是不是沒有進行變數提升呢?
根據ES6標準中對於let/const宣告的章節13.3.1 let/const宣告,有以下的文字說明:
The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable’s LexicalBinding is evaluated.也就是說其實let/const申明的變數,js引擎對其進行預編譯時也會進行變數提升(hoist),但是這時候並沒有進行詞法繫結,也就是對宣告語句進行求值運算,是不可以被訪問的,訪問就會丟擲錯誤,這也被稱為暫時性死區(TDZ),如以下程式碼段:
let total = 0; function func(num1, num2) { console.log(total); //出現TDZ,訪問丟擲ReferenceError錯誤 let total = num1 + num2; console.log(total); } func(100 , 200); console.log(total);
那麼這時如果把let換成var呢,會出現什麼現象呢?
var total = 0;
function func(num1, num2) {
console.log(total);
var total = num1 + num2;
console.log(total);
}
func(100 , 200);
console.log(total);
也就是變數的查詢會先在區域性作用域內進行,如果沒有,才會追溯到上級作用域。由於變數提升的作用,func函式內第一次列印total會打印出undefined, 而不是0,也並不會丟擲任何錯誤。
總結:養成良好的程式碼習慣,變數的使用遵循先宣告再使用的規則,就不會遇到這些問題。