溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么理解ES6塊級(jí)作用域

發(fā)布時(shí)間:2021-11-03 14:25:37 來源:億速云 閱讀:129 作者:iii 欄目:web開發(fā)

這篇文章主要介紹“怎么理解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í)用的文章!

向AI問一下細(xì)節(jié)

免責(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)容。

es6
AI