es5和es6的區(qū)別里,關(guān)于塊級(jí)綁定是被津津樂道的。之前沒有記錄,今天就把它記錄下來(lái)。
我們知道var會(huì)有變量提升。
es6的let和const可以避免這個(gè),且會(huì)生成塊級(jí)作用域。
塊級(jí)聲明
-
function里面 - 塊內(nèi)(由
{和}字符表示)
let 聲明
function getValue(condition) {
if (condition) {
let value = "blue";
// other code
return value;
} else {
// value 不存在這里
return null;
}
// value 不存在這里
}
無(wú)重復(fù)聲明
var count = 30;
// Syntax error
let count = 40;
上面會(huì)報(bào)錯(cuò),count被聲明兩次:一次使用var,一次使用let。因?yàn)?code>let不會(huì)重新定義已存在于同一范圍內(nèi)的標(biāo)識(shí)符,所以let聲明將引發(fā)錯(cuò)誤。
var count = 30;
// Does not throw an error
if (condition) {
let count = 40;
// more code
}
這個(gè)不會(huì)報(bào)錯(cuò),因?yàn)閷?shí)在新的作用域(塊級(jí))創(chuàng)建的新變量。
The Temporal Dead Zone
if (condition) {
console.log(typeof value); // ReferenceError!
let value = "blue";
}
這個(gè)就是所謂的tdz,TDZ永遠(yuǎn)不會(huì)在ECMAScript規(guī)范中明確命名,但該術(shù)語(yǔ)通常用于描述為什么let和const聲明在聲明之前無(wú)法訪問(wèn)。
當(dāng)js引擎查看即將發(fā)生的塊并找到變量聲明時(shí),它會(huì)將聲明提升到函數(shù)頂部或全局范圍(對(duì)于var),或者將聲明放在TDZ中(對(duì)于let和const)。
上面的例子會(huì)報(bào)錯(cuò),因?yàn)樵谶@個(gè)塊級(jí)作用域內(nèi)的聲明之前存在這個(gè)TDZ,但是你可以在塊級(jí)作用域外使用:
console.log(typeof value); // "undefined"
if (condition) {
let value = "blue";
}
TDZ只是塊綁定的一個(gè)獨(dú)特方面。另一個(gè)獨(dú)特的方面與它們?cè)谘h(huán)內(nèi)的使用有關(guān)。
block binding in loops
var funcs = [];
for (var i = 0; i < 10; i++) {
funcs.push(function() { console.log(i); });
}
funcs.forEach(function(func) {
func(); // 輸出 "10" 十次。
});
在es6之前解決這個(gè)問(wèn)題可以使用IIFE。
var funcs = [];
for (var i = 0; i < 10; i++) {
funcs.push((function(value) {
return function() {
console.log(value);
}
}(i)));
}
funcs.forEach(function(func) {
func(); // 0,1,2,...
});
但是es6之后,可以直接使用let。
var funcs = [];
for (let i = 0; i < 10; i++) {
funcs.push(function() {
console.log(i);
});
}
funcs.forEach(function(func) {
func(); // outputs 0, then 1, then 2, up to 9
})
這個(gè)是因?yàn)樵诿看蔚牡?,都?huì)創(chuàng)建一個(gè)新的變量,這就導(dǎo)致每個(gè)創(chuàng)建的內(nèi)部的方法都有一個(gè)自己的變量。每次創(chuàng)建的時(shí)候,都會(huì)分配值。
重要的是要理解循環(huán)中l(wèi)et聲明的行為是規(guī)范中特別定義的行為,并不一定與let的非提升特性有關(guān)。實(shí)際上,let的早期實(shí)現(xiàn)沒有這種行為,因?yàn)樗院笤谶^(guò)程中添加。
const 和 let
其實(shí)const的行為和let的行為差不多。只是const定義的是常量,不變的數(shù)據(jù)。let定義的是改變的數(shù)據(jù)。并且在聲明const的時(shí)候必須存在值。
const name; //error
const name = 'my name'
name = 'your name' // error
let age;
age = 18;
對(duì)于const需要明確一點(diǎn),就是改變的是什么?看下面這個(gè)。
const person = {
name: "Nicholas"
};
// works
person.name = "Greg";
// throws an error
person = {
name: "Greg"
};
可以更改person.name而不會(huì)導(dǎo)致錯(cuò)誤,因?yàn)檫@會(huì)更改person包含的內(nèi)容,并且不會(huì)更改person綁定的值。當(dāng)此代碼嘗試為person分配值(從而嘗試更改綁定)時(shí),將引發(fā)錯(cuò)誤。const如何與對(duì)象一起工作的這種微妙之處很容易被誤解。請(qǐng)記?。?strong>const阻止修改綁定,而不是阻止修改綁定值。