轉(zhuǎn)載自程序員是粉色的
先說區(qū)別
1.使用var聲明的變量,其作用域為該語句所在的函數(shù)內(nèi),且存在變量提升現(xiàn)象绢片;
2.使用let聲明的變量县忌,其作用域為該語句所在的代碼塊內(nèi),不存在變量提升事示;
3.let不允許在相同作用域內(nèi)礼患,重復(fù)聲明同一個變量是钥。
1.基本語法
{
let a = 125;
var b = 521;
}
a // Uncaught ReferenceError: a is not defined
b // 521
上面代碼中掠归,使用let聲明的變量報錯,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
上面代碼中弹囚,計數(shù)器i只在for循壞體內(nèi)有效厨相,再循環(huán)體外引用就會報錯。
下面是常見的面試題目:
for (var i = 0; i <10; i++) {
setTimeout(function() { // 同步注冊回調(diào)函數(shù)到 異步的 宏任務(wù)隊列余寥。
console.log(i); // 執(zhí)行此代碼時领铐,同步代碼for循環(huán)已經(jīng)執(zhí)行完成
}, 0);
}
// 輸出結(jié)果
//10 共10個
如果把 var改成 let聲明:
// i雖然在全局作用域聲明悯森,但是在for循環(huán)體局部作用域中使用的時候宋舷,變量會被固定,不受外界干擾瓢姻。
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)還有一個特別之處绎狭,就是設(shè)置循環(huán)變量的那部分是一個父作用域,而循環(huán)體內(nèi)部是一個單獨的子作用域褥傍。
for (let i = 0; i < 3; i++) {
let i = 'love';
console.log(i);
}
// love
// love
// love
上面代碼正確運行儡嘶,輸出了 3 次abc。這表明函數(shù)內(nèi)部的變量i與循環(huán)變量i不在同一個作用域恍风,有各自單獨的作用域蹦狂。
2.不存在變量提升
var命令會發(fā)生”變量提升“現(xiàn)象,即變量可以在聲明之前使用朋贬,值為undefined凯楔。
let命令則不同,它所聲明的變量一定要在聲明后使用锦募,否則報錯摆屯。
// var 的情況
console.log(ar); // 輸出undefined
var ar = 512;
// let 的情況
console.log(et); // 報錯ReferenceError
let et = 512;
上面代碼變量ar用var聲明,會發(fā)生變量提升糠亩,因沒有值虐骑,所以會輸出undefined。變量et用let聲明的則不會發(fā)生變量提升赎线。
暫時性死區(qū)
var tmp=521;
if(true){
tmp='abc';//ReferenceError: tmp is not defined
let tmp;
}
上面代碼中廷没,存在全局變量tmp,但是塊級作用域內(nèi)let又聲明了一個局部變量tmp氛驮,導(dǎo)致后者綁定這個塊級作用域腕柜,所以在let聲明變量前,對tmp賦值會報錯。
ES6 明確規(guī)定盏缤,如果區(qū)塊中存在let和const命令砰蠢,這個區(qū)塊對這些命令聲明的變量,從一開始就形成了封閉作用域唉铜。凡是在聲明之前就使用這些變量台舱,就會報錯。(使用const聲明的是常量潭流,在后面出現(xiàn)的代碼中不能再修改該常量的值竞惋。)
總之,在代碼塊內(nèi)灰嫉,使用let命令聲明變量之前拆宛,該變量都是不可用的。這在語法上讼撒,稱為“暫時性死區(qū)”(temporal dead zone浑厚,簡稱 TDZ)。
不允許重復(fù)聲明
let不允許在相同作用域內(nèi)根盒,重復(fù)聲明同一個變量钳幅。
// 報錯
function func() {
let a = 10;
var a = 1;
}
// 報錯
function func() {
let a = 10;
let a = 1;
}
因此,不能在函數(shù)內(nèi)部重新聲明參數(shù)炎滞。
function func(arg) {
let arg; // 報錯
}
function func(arg) {
{
let arg; // 不報錯
}
}