ES5對於變量而言,沒有塊級作用域這一說,存在的是函數作用域,但是在ES6中,let和const是屬於塊級作用域的聲明,需要先聲明,再使用,有點想起當時使用VC的場景,哈哈哈~
let
let的出現爲JavaScript增加了塊級作用域,使用let定義的變量,外層作用域是無法讀取內層作用域的變量的
暫時性死區
if(true) {
//TDZ開始
tmp = 'abc';
console.log(tmp);
let tmp; // TDZ結束
console.log(tmp);
tmp = 123;
console.log(tmp);
}
babel編譯之後的代碼
'use strict';
if (true) {
//TDZ開始
tmp = 'abc';
console.log(tmp);
var tmp = void 0; // TDZ結束
console.log(tmp);
tmp = 123;
console.log(tmp);
}
在看到這裏我覺得相比較而言就是定義tmp的時候,babel後多了一個void 0
, 於是我去查詢了一下,總結出下面的東西,關於void的介紹
void(0) 相當於void 0,在ES5之前,window下的undefined是可以被重寫的,於是導致了某些極端情況下使用undefined會出現一定的差錯,所以用void 0是防止undefined被重寫而出現判斷不準確的情況,非嚴格模式下,undefined是可以重寫的,嚴格模式是不能重寫的
作用:1)防止被重寫 2)減少字節,undefined屬於基本類型,佔用8個字節,而void 0代替undefined省了三個字節
對比以下兩段代碼
1)x賦默認值,y的值等於x
function bar(x = 1, y = x) {
return [x, y];
}
var res = bar();
console.log(res);
babel之後的代碼
"use strict";
function bar() {
var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x;
return [x, y];
}
var res = bar();
console.log(res);
2)x賦值爲y,y賦默認值爲1
function bar(x = y, y = 1) {
return [x, y];
}
var res = bar();
console.log(res);
這個時候就出錯了,x=y
,此時y還沒有聲明,屬於死區,babel的代碼與上面類似,這裏就不再贅述
塊級作用域
function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重複聲明一次函數f
function f() { console.log('I am inside!'); }
}
f();
}());
在ES5的執行環境中輸出的結果是”I am inside!”,但是在ES6的環境中,這是會報錯的,但是利用bable編譯的代碼,執行的結果是“I am outside!”,利用babel編譯的代碼如下
'use strict';
function f() {
console.log('I am outside!');
}
(function () {
if (false) {
// 重複聲明一次函數f
var _f = function _f() {
console.log('I am inside!');
};
}
f();
})();
const
const聲明一個只讀的變量,一旦聲明,常量的值就不能改變
const PI = 3.1415;
console.log(PI);
PI = 3;
運行的時候,會出現Assignment to constant variable.
的錯誤提示
const obj = {name : 'vam'};
obj.name = 'uu';
上面的代碼運行並沒有錯誤提示,const保證的不是變量的值不發生改變,而是變量指向的那個內存地址不得變動,對於簡單類型(undefined、null、boolean、number、string)而言,值就保存在變量指向的那個內存空間,等同於常量,對於複雜類型,只是保存的一個指針,這個指針指向的空間裏的內容就是無關緊要的
const和let一樣存在暫時性死區,只能在聲明的位置之後使用
參考:《ECMAScript 6入門》