您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么理解ES6塊級(jí)作用域”,在日常操作中,相信很多人在怎么理解ES6塊級(jí)作用域問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”怎么理解ES6塊級(jí)作用域”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
作用域
作用域指變量所作用的范圍,在 Javascript 中有兩種作用域:
全局作用域
函數(shù)作用域
變量提升
變量提升(Hoisting)被認(rèn)為是, Javascript 中執(zhí)行上下文 (特別是創(chuàng)建和執(zhí)行階段)工作方式的一種認(rèn)識(shí)。具體表現(xiàn)就是所有通過 var 聲明的變量會(huì)提升到當(dāng)前作用域的最前面。
function foo() {
console.log(temp);
}
function bar() {
console.log(temp);
var temp;
}
foo(); // ReferenceError: temp is not defined
bar(); // undefined
可以看到用 var 聲明了的并不會(huì)報(bào)錯(cuò)。因?yàn)槠鋵?shí)函數(shù) bar 等同于
function bar() {
var temp;
console.log(temp);
}
大多數(shù)類 C 語言語法的語言都擁有塊級(jí)作用域。在一個(gè)代碼塊(括在一對(duì)花括號(hào)中的一組語句)中定義的所有變量在代碼塊的外部是不可見的。定義在代碼塊中的變量在代碼塊被執(zhí)行結(jié)束后會(huì)變釋放掉。這是件好事。
糟糕的是,盡管 Javascript 的代碼貌似支持塊級(jí)作用域,但實(shí)際上 Javascript 并不支持(就是因?yàn)橛凶兞刻嵘_@個(gè)混淆之處可能成為錯(cuò)誤之源。
所以在 ES6 中規(guī)定了 let 和 const 來支持塊級(jí)作用域。但是,是不是真的提升就不存在了呢,可以看下面暫時(shí)性死區(qū)這部分。
let
let 可以理解為『更完美的 var』,使用方法很簡(jiǎn)單;
let foo = 3;
使用方法基本和 var 相同,而且聲明的變量只在其塊和子塊中可用,這點(diǎn)也與 var 相同。 二者之間最主要的區(qū)別在于 var 聲明的變量的作用域是整個(gè)封閉函數(shù)。
function foo() {
if(true) {
var temp = 5;
console.log(temp);
}
console.log(temp);
}
function bar() {
if(true) {
let temp = 5;
console.log(temp);
}
console.log(temp);
}
foo(); // 5 和 5
bar(); // 5 和 "ReferenceError: temp is not defined
let 聲明的變量的作用域只是外層塊,而不是整個(gè)外層函數(shù)。
我們可以利用這個(gè)特性來替代立即執(zhí)行函數(shù)(IIFE)。
// IIFE
(function(){
var temp = xxx;
/*
other code
*/}())
// 塊級(jí)
{
let temp = xxx;
/*
other code
*/
}
const
const 的用法跟 let 差不多,但是 const 一定要初始化, 不初始化是會(huì)報(bào)錯(cuò)的。
const temp = 4;// 沒有初始化報(bào)錯(cuò)
const t; // SyntaxError: Missing initializer in const declaration
const 是塊級(jí)作用域,const 跟 let 的語義相似,就是用來聲明常量的,一旦聲明了就不能更改。值得注意的是 const 聲明的變量記錄的是指針,不可更改的是指針,如果 const 所聲明的是對(duì)象,對(duì)象的內(nèi)容還是可以修改的。
// 重新賦值聲明導(dǎo)致報(bào)錯(cuò)
const PI = 3.14;
PI = 3.1415926; // TypeError: Assignment to constant variable.
// 給對(duì)象增加屬性不會(huì)導(dǎo)致 obj 的指針變化,所以不會(huì)報(bào)錯(cuò)
const obj = { foo: 2 };
obj.bar = 3;
console.log(obj); // {foo: 2, bar: 3}
暫時(shí)性死區(qū)
使用 let 或 const 聲明的變量,在聲明沒有到達(dá)之前,訪問該變量都會(huì)導(dǎo)致報(bào)錯(cuò),就連一直以為安全的 typeof 也不再安全。
// TDZ1
function foo() { // TDZ 開始
console.log(typeof temp);
let temp = 5; // TDZ 結(jié)束
}
foo(); // ReferenceError: temp is not defined
報(bào)的錯(cuò)是 ReferenceError,如果使用 var 聲明的話,temp 輸出應(yīng)該是 undefined,從 let 聲明的變量的塊的第一行,到聲明變量之間的這個(gè)區(qū)域被稱作暫時(shí)性死區(qū)(TDZ)。凡是在這個(gè)區(qū)域使用這些變量都會(huì)報(bào)錯(cuò)。
// TDZ2
function bar() {
console.log(typeof temp);
}
bar(); // undefined
看到上面兩個(gè)例子仔細(xì)思考有沒有覺得想到點(diǎn)什么?
在函數(shù)里沒有用 let 聲明 temp 的時(shí)候,temp 是 undefined,講道理在 let 聲明前也應(yīng)該是 temp,然而 foo 函數(shù)卻報(bào)了錯(cuò),證明了就算是在未到達(dá) let 聲明的地方,但是在用 let 之前已經(jīng)起到了作用。這是不是說明其實(shí) let 也有提升,只是在 TDZ 使用的時(shí)候報(bào)錯(cuò)了,而不是 undefined。
事實(shí)上,當(dāng) JS 引擎檢視下面的代碼塊有變量聲明時(shí),對(duì)于 var 聲明的變量,會(huì)將聲明提升到函數(shù)或全局作用域的頂部,而對(duì) let 或 const 的時(shí)候會(huì)將聲明放在暫時(shí)性死區(qū)內(nèi)。任何在暫時(shí)性死區(qū)內(nèi)訪問變量的企圖都會(huì)導(dǎo)致“運(yùn)行時(shí)”錯(cuò)誤(runtime error)。只有執(zhí)行到變量的聲明語句時(shí),該變量才會(huì)從暫時(shí)性死區(qū)內(nèi)被移除并可以安全使用。
禁止重復(fù)聲明
在同一個(gè)塊內(nèi),let 和 const 不能聲明相同的標(biāo)識(shí)符。禁止的情況包括:
let 或 const 和 let 或 const
var 和 let 或者 const
函數(shù)參數(shù)與 let 或 const
// let 和 let
let foo = 1;
let foo = 2;
// let 和 const
let foo = 1;
const foo = 1;
// var 與 let
var foo = 1;
let foo = 1;
// 函數(shù)參數(shù)與 let
function bar(foo) {
let foo = 1;
}
以上情況都是會(huì)報(bào) SyntaxError。但是在嵌套的作用域內(nèi)使用 let 聲明同一變量是被允許的。
var foo = 1;
{
// 不會(huì)報(bào)錯(cuò)
let = 2;
// other code
}
同時(shí)因?yàn)槭?let 和 const 是塊級(jí)作用域,聲明的變量在當(dāng)前塊使用完之后就會(huì)被釋放,所以就算使用相同的標(biāo)識(shí)符也不會(huì)覆蓋外部作用域的變量, 而 var 是會(huì)覆蓋外部作用域的變量的。
function foo() {
var bar = 1;
{
let bar = 2;
}
console.log(bar);
}
function zoo() {
var bar = 1;
{
var bar = 2;
}
console.log(bar);
}
foo(); // 1
zoo(); // 2
最佳實(shí)踐
在 ES6 的發(fā)展階段,被廣泛認(rèn)可的變量聲明方式是:默認(rèn)情況下應(yīng)當(dāng)使用 let 而不是 var 。對(duì)于多數(shù) JS 開發(fā)者來說, let 的行為方式正是 var 本應(yīng)有的方式,因此直接用 let替代 var 更符合邏輯。在這種情況下,你應(yīng)當(dāng)對(duì)需要受到保護(hù)的變量使用 const。
在默認(rèn)情況下使用 const ,而只在你知道變量值需要被更改的情況下才使用 let 。這在代碼中能確保基本層次的不可變性,有助于防止某些類型的錯(cuò)誤。
思考題
兩個(gè)思考題,我會(huì)把答案放在評(píng)論中。請(qǐng)點(diǎn)擊原文鏈接去看答案
// 思考題 1
switch (x) {
case 0:
let foo;
break;
case 1:
let foo; // TypeError for redeclaration.
break;
}
// 思考題 2
function bar(){
var foo = 1;
if (true) {
let foo = (foo + 2);
}
}
bar();
到此,關(guān)于“怎么理解ES6塊級(jí)作用域”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。