使用let,不會造成變量提升
ES5
console.log(test); //結果是undefined
var test = 'test';
可以理解為:
var test;
console.log(test); //結果是undefined
test = 'test';
ES6
console.log(test); //結果是ReferenceError:test is not defined
let test = 'test';
因為不存在變量提升,可以理解為:
console.log(test);
let test; //上不去哩,所以報錯了。
test = 'test';
作用在塊級作用域
首先要科普一下塊級作用域:
在ES6之前javascript是用函數function來劃分作用域,于是定義的變量作用在各個函數里,單獨或者嵌套,也造成了函數作用域鏈。
現在ES6定義了塊級作用域,用{}(if、for等使用了{}才具備塊級作用域的條件)劃分塊級作用域,let在塊級作用域定義的變量在離開塊級作用域的時候會被銷毀,所以在塊級作用域內定義的變量在塊級作用域外訪問的話會報引用錯誤(ReferenceError)
ES5
{
var a = 1;
}
console.log(a); //結果為1
ES6
{
let a = 1;
}
console.log(a) //結果是ReferenceError: a is not defined
不允許重復聲明變量
ES5
{
var a = 1;
var a = 2; //我照樣過得好好的~
}
ES6
{
let a = 1;
let a = 2; //出錯啦~,SyntaxError: Identifier 'a' has already been declared
}
暫時性死區(temporal dead zone,簡稱 TDZ)
ES6明確規定,如果區塊中存在let和const命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。
沒有let的區塊(無論是es5還是es6)
{
tmp = 'abc';
console.log(tmp); //結果為abc
}
{
tmp = 'abc';
console.log(tmp); //結果為abc
var tmp; //這里定義的tmp將會變量提升,相當于移動這個語句在tmp = 'abc'上面。
}
有let的區塊
{
// TDZ開始,因為下面出現了let tmp,所以let以上的語句出現暫時性死區
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ結束,let tmp以下的語句沒有暫時性死區,因為這里let tmp沒有賦值,所以下面報undefined的錯
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
typeof
typeof也會報錯
{
typeof test; //ReferenceError: test is not defined
let test = 2;
}
隱蔽的暫時性死區
function bar(x = y,y = 2){
return [x,y]
}
bar(); //ReferenceError: y is not defined
在塊級作用域里聲明函數
ES5嚴格模式下(非嚴格模式下不會報錯)
'use strict';
if (true){
function test(){console.log('test')}
}
test(); //ReferenceError:test is not defined
ES6允許在塊級作用域聲明函數
非嚴格模式
if (true) {
function test() {console.log('test')}
}
test(); //結果為test
嚴格模式
不用var、let、const定義:
'use strict';
if (true) {
function test() {console.log('test')} //由于function沒有加var、let、const定義,所以此函數的作用域是全局的
}
test() //結果為test
var:
'use strict';
if (true){
var test = function(){console.log('test')} //由于function是用var定義的,所以此函數是當前function作用域,此處為global
}
test() //結果為test
let或者const:
'use strict';
if (true){
let test = function(){console.log('test')} //由于function是用let定義的,所以此函數是當前塊級作用域,即是{}包括的區域,離開之后變量被銷毀
}
test() //結果為ReferenceError: test is not defined
const定義常量
不可以重新賦值
const test = 1;
test = 0; //TypeError: Assignment to constant variable.
一旦定義就必須初始化
const test; //SyntaxError: Missing initializer in const declaration
const定義的地址不能改變,但是內容可以改變
const test = [];
test.push('test');
console.log(test); //['test']