目錄
1.let命令
簡單地說就是一個變量聲明標識,和var的作用是相同的,但是又和var有很大的區別.
1.1 塊級作用域
{
let a = 1;
var b = 2;
}
console.log(a,b);//b可以打印,a不可以
在代碼塊中let聲明的變量只能在該代碼塊有效,而var超出代碼塊依然有效.
1.2 for循環
var a = [];
var b = [];
for(let i = 0; i < 6; i ++)
a[i] = function (){
console.log(i)
}
for(var j = 0; j < 6; j ++)
b[j] = function (){
console.log(j)
}
a[4]();//4
a[4]();//6
let聲明的變量的局部的,所以輸出是對應的數字;
var聲明的變量是全聚德,所以輸出都是i最後的狀態,及6.
1.3 變量提升
相比var,let不存在變量提升,所以要使用一個let聲明的變量,必須先聲明再使用.
1.4 暫時性死區
只要塊級作用域內存在let命令,它所聲明的變量就綁定了這個區域,不在受外部的影響。
var tmp = 123;
if(true){
tmp = 'abc';//ReferenceError
let tmp;
}
暫時性死區(temporal dead zone 簡稱TDZ):在代碼塊內使用let命令聲明變量之前,該變量都是不可用的。
if(true){
//TDZ開始
tmp = 'abc';
console.log(tmp);
let tmp;//TDZ結束
console.log(tmp);
tmp = 123;
console.log(tmp);
}
function bar(x = y, y = 2){
return [x, y];
}
function bar2(x = 2, y = x){
return [x, y];
}
bar();//報錯
bar2();//[2, 2]
x的默認參數是y,但是此時y還沒有聲明,所以是TDZ。
1.5 不允許重複聲明
let不允許在相同作用域內重複聲明同一個變量。
//error
function(){
let a = 10;
var a = 1;
}
//error
function(){
let a = 10;
let a = 1;
}
//error
function func(arg){
let arg;
}
//right
function func(arg){
{
let arg;
}
}
2.塊級作用域
傳統ES5語法問題:
場景一
變量提升導致內層的tmp變量覆蓋了外層的tmp變量。
var tmp = new Date();
function f(){
console.log(tmp);
if(false){
var tmp = "hello world";
}
}
f()//undefined
場景二
變量i在循環結束後泄露成了全局變量。
var s = 'hello';
for (var i = 0; i < s.length; i++){
console.log(s[i])
}
console.log(i)
將上面2個場景中的var命令變成let命令就可以避免上述的問題。
function f(){
console.log('I am outside!');
}
(function(){
if(false){
function f(){
console.log('I am inside!');
}
}
f();
}());
ES5存在變量提升:I am inside!
ES6支持塊級作用域:I am outside!
如需要在外部使用塊級作用域內部的變量,則需要先在外部先聲明,在內部賦值。
let f;
{
let a = 'secret';
f = function(){
return a;
}
}
f()//'secret'
3.const命令
const 用來生命常量,一旦聲明,其值就不可改變。
const PI = 3.1414;
PI //3.1415
PI = 3;//error
const聲明時就需要立即初始化,不能留到以後賦值。
const foo;//error
const作用域和let命令相同:只在聲明所在的塊級作用域有效;不存在變量提升,存在暫時性死區;不可重複聲明變量。
if(true){
const MAX = 5;
}
MAX//error
if(true){
console.log(MAX);//error
const MAX = 5;
}
var message = 'hello!';
let age = 25;
const message = 'Goodbye!';//error
const age = 30;//error
複合型變量,變量名不指向數據,而是指向數據所在的地址,const命令只是保證變量名指向的地址不變,並不保證該地址的數據不變。
const foo = {};
foo.prop = 123;
foo.prop //123
foo = {} //error
const a = [];
a.push('hello');//right
a.length = 0;//right
a = ['Dave'];//error