之前通過babel-node將es6轉為es5后結合生成的es5代碼認為let是在es5的基礎上封裝的語法糖,並且通過babel-node執行沒有報ReferenceError而認為其有變量提升,其實這是錯誤的,let是es中新加入的一個標識符而已。並且沒有變量提升。特此勘正。
1、let中沒有變量提升。
在通過babel-node執行es6的代碼時,是將es6轉換為es5后去執行的,所以下面的代碼
if (true) { // TDZ開始 tmp = 'abc'; // ReferenceError console.log(tmp); // ReferenceError let tmp; // TDZ結束 console.log(tmp); // undefined tmp = 123; console.log(tmp); // 123 }
轉換為es5后的代碼為
if (true) { _tmp = 'abc'; // console.log(_tmp); // abc var _tmp = undefined; console.log(_tmp); // undefined _tmp = 123; console.log(_tmp); // 123 }
並且輸出的是undefined,而不是ReferenceError,但是在這里就不要認為let存在變量聲明,babel-node在執行的過程中會將代碼轉為es5,
但是在正式的es6環境下會輸出ReferenceError, 和var聲明的變量不一樣,var 是當一個變量所在的函數被解析的時候,就為函數創建了一個
函數作用域,變量也被初始化為undefined,然后當函數執行到該變量聲明的地方的時候,就會對該對象進行初始化,如果沒有賦值,那么該變量
的值就是undefined。而let聲明的變量存在TDZ(The temporal dead zone) 什么意思呢?當let所在的包含塊被解析時,會創建一個塊級作用
域,但是此時變量是沒有初始化,在該塊級作用域中嘗試在let聲明之前獲取它的值或者給它賦值都將會報ReferenceError的錯誤。當執行到let
聲明的變量的時候會對該變量進行初始化,如果沒有賦值,那么該變量的值是undefined。在這里要感謝WhatTheFsck的指點。
最后再小結一下let的知識吧
1、let擁有塊級作用域
2、let在塊級作用域中不存在變量提升
3、不能在同一作用域中(函數作用域和塊級作用域)用let聲明相同的變量
外文參考: http://www.2ality.com/2015/02/es6-scoping.html