先說區(qū)別
1.使用var聲明的變量,其作用域?yàn)樵撜Z句所在的函數(shù)內(nèi),且存在變量提升現(xiàn)象;
2.使用let聲明的變量,其作用域?yàn)樵撜Z句所在的代碼塊內(nèi),不存在變量提升;
3.let不允許在相同作用域內(nèi),重復(fù)聲明同一個(gè)變量。
1.基本語法
{
let a = 125;
var b = 521;
}
a // Uncaught ReferenceError: a is not defined
b // 521
上面代碼中,使用let聲明的變量報(bào)錯(cuò),var聲明的返回正確的值,這說明,let聲明的變量只在它所在的代碼塊有效。
let配合for循環(huán)的應(yīng)用
for (let i = 0; i < 5; i++) {
console.log(i); //0 1 2 3 4
}
console.log(i); //ReferenceError: i is not defined
上面代碼中,計(jì)數(shù)器i只在for循壞體內(nèi)有效,再循環(huán)體外引用就會(huì)報(bào)錯(cuò)。
下面是常見的面試題目:
for (var i = 0; i <10; i++) {
setTimeout(function() { // 同步注冊(cè)回調(diào)函數(shù)到 異步的 宏任務(wù)隊(duì)列。
console.log(i); // 執(zhí)行此代碼時(shí),同步代碼for循環(huán)已經(jīng)執(zhí)行完成
}, 0);
}
// 輸出結(jié)果
//10 共10個(gè)
如果把 var改成 let聲明:
// i雖然在全局作用域聲明,但是在for循環(huán)體局部作用域中使用的時(shí)候,變量會(huì)被固定,不受外界干擾。
for (let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i); // i 是循環(huán)體內(nèi)局部作用域,不受外界影響。
}, 0);
}
// 輸出結(jié)果:
0 1 2 3 4 5 6 7 8 9
另外,for循環(huán)還有一個(gè)特別之處,就是設(shè)置循環(huán)變量的那部分是一個(gè)父作用域,而循環(huán)體內(nèi)部是一個(gè)單獨(dú)的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'love';
console.log(i);
}
// love
// love
// love
上面代碼正確運(yùn)行,輸出了 3 次abc。這表明函數(shù)內(nèi)部的變量i與循環(huán)變量i不在同一個(gè)作用域,有各自單獨(dú)的作用域。
2.不存在變量提升
var命令會(huì)發(fā)生”變量提升“現(xiàn)象,即變量可以在聲明之前使用,值為undefined。
let命令則不同,它所聲明的變量一定要在聲明后使用,否則報(bào)錯(cuò)。
// var 的情況
console.log(ar); // 輸出undefined
var ar = 512;
// let 的情況
console.log(et); // 報(bào)錯(cuò)ReferenceError
let et = 512;
上面代碼變量ar用var聲明,會(huì)發(fā)生變量提升,因沒有值,所以會(huì)輸出undefined。變量et用let聲明的則不會(huì)發(fā)生變量提升。
暫時(shí)性死區(qū)
var tmp=521;
if(true){
tmp='abc';//ReferenceError: tmp is not defined
let tmp;
}
上面代碼中,存在全局變量tmp,但是塊級(jí)作用域內(nèi)let又聲明了一個(gè)局部變量tmp,導(dǎo)致后者綁定這個(gè)塊級(jí)作用域,所以在let聲明變量前,對(duì)tmp賦值會(huì)報(bào)錯(cuò)。
ES6 明確規(guī)定,如果區(qū)塊中存在let和const命令,這個(gè)區(qū)塊對(duì)這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會(huì)報(bào)錯(cuò)。(使用const聲明的是常量,在后面出現(xiàn)的代碼中不能再修改該常量的值。)
總之,在代碼塊內(nèi),使用let命令聲明變量之前,該變量都是不可用的。這在語法上,稱為“暫時(shí)性死區(qū)”(temporal dead zone,簡(jiǎn)稱 TDZ)。
不允許重復(fù)聲明
let不允許在相同作用域內(nèi),重復(fù)聲明同一個(gè)變量。
// 報(bào)錯(cuò)
function func() {
let a = 10;
var a = 1;
}
// 報(bào)錯(cuò)
function func() {
let a = 10;
let a = 1;
}
因此,不能在函數(shù)內(nèi)部重新聲明參數(shù)。
function func(arg) {
let arg; // 報(bào)錯(cuò)
}
function func(arg) {
{
let arg; // 不報(bào)錯(cuò)
}
}