日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
知道臨時(shí)死區(qū)你才能更好的使用JS變量

首先,來(lái)個(gè)一個(gè)簡(jiǎn)單的問題。下列哪段代碼會(huì)產(chǎn)生錯(cuò)誤:

成都創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比新平網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式新平網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋新平地區(qū)。費(fèi)用合理售后完善,10余年實(shí)體公司更值得信賴。

第一個(gè)創(chuàng)建實(shí)例,然后定義使用的類:

 
 
 
 
  1. new Car('red'); // 是否會(huì)報(bào)錯(cuò)? 
  2.  
  3. class Car { 
  4.   constructor(color) { 
  5.     this.color = color; 
  6.   } 

或者先于函數(shù)定義之前調(diào)用函數(shù):

 
 
 
 
  1. greet('World'); // 是否會(huì)報(bào)錯(cuò)? 
  2.  
  3. function greet(who) { 
  4.   return `Hello, ${who}!`; 
  5. }    

正確的答案是:第一個(gè)代碼片段會(huì)報(bào) ReferenceError: Cannot access 'Car' before initialization 錯(cuò)誤。第二個(gè)代碼正常運(yùn)行。

如果你的答案與上述不同,或者你在不知道這背后的原理是什么而進(jìn)行了猜測(cè),那么你需要掌握臨時(shí)死區(qū)(TDZ)的知識(shí)。

TDZ 管理 let、const 和 class 語(yǔ)法的可用性。變量在 JS 中的工作方式非常重要。

1. 什么是臨時(shí)死區(qū)

咱們先從一個(gè)簡(jiǎn)單的 const 變量聲明開始。首先聲明并初始化變量,然后訪問它,一切正常運(yùn)行:

 
 
 
 
  1. const white = '#FFFFFF';  
  2. white; // => '#FFFFFF' 

那如果在 聲明之前訪問 white 變量,會(huì)怎么樣?

 
 
 
 
  1. white; // throws `ReferenceError`  
  2. const white = '#FFFFFF';  
  3. white; 

在 const white = '#FFFFFF' 語(yǔ)句之前的代碼行中,變量 white 位于臨時(shí)死區(qū)。

在 TDZ 中訪問 white 后,JS拋出ReferenceError: Cannot access 'white' before initialization

臨時(shí)死區(qū)語(yǔ)義禁止在變量聲明之前訪問它。它加強(qiáng)了順序:在聲明之前不要使用任何東西。

2. 受 TDZ 影響的聲明

來(lái)看看受 TDZ 影響的聲明。

(1) const變量

如前所述,const 變量位于聲明和初始化行之前的 TDZ 中:

 
 
 
 
  1. // 無(wú)法工作 
  2. pi; // throws `ReferenceError` 
  3.  
  4. const pi = 3.14; 

咱們必須在聲明之后使用 const 變量:

 
 
 
 
  1. const pi = 3.14; 
  2.  
  3. // Works! 
  4. pi; // => 3.14 

(2) let 變量

在聲明行之前,let 聲明語(yǔ)句也會(huì)受到 TDZ 的影響:

 
 
 
 
  1. // 無(wú)法工作 
  2. count; // throws `ReferenceError` 
  3.  
  4. let count; 
  5.  
  6. count = 10; 

同樣,僅在聲明之后使用 let 變量:

 
 
 
 
  1. let count; 
  2.  
  3. // Works! 
  4. count; // => undefined 
  5.  
  6. count = 10; 
  7.  
  8. // Works! 
  9. count; // => 10 

(3) class 的聲明

正如在介紹中看到的,在定義 class 之前不能使用它:

 
 
 
 
  1. // 無(wú)法工作 
  2. const myNissan = new Car('red'); // throws `ReferenceError` 
  3.  
  4. class Car { 
  5.   constructor(color) { 
  6.     this.color = color; 
  7.   } 

(4) 構(gòu)造函數(shù)內(nèi)部的 super()

如果在構(gòu)造函數(shù)中調(diào)用 super()之前擴(kuò)展父類,則此綁定位于 TDZ 中。

 
 
 
 
  1. class MuscleCar extends Car { 
  2.   constructor(color, power) { 
  3.     this.power = power; 
  4.     super(color); 
  5.   } 
  6.  
  7. // Does not work! 
  8. const myCar = new MuscleCar('blue', '300HP'); // `ReferenceError` 

在構(gòu)造 constructor() 中,在調(diào)用super()之前不能使用 this。

TDZ 建議調(diào)用父構(gòu)造函數(shù)來(lái)初始化實(shí)例。這樣做之后,實(shí)例就準(zhǔn)備好了,就可以在子構(gòu)造函數(shù)中進(jìn)行調(diào)整。

 
 
 
 
  1. class MuscleCar extends Car { 
  2.   constructor(color, power) { 
  3.     super(color); 
  4.     this.power = power; 
  5.   } 
  6.  
  7. // Works! 
  8. const myCar = new MuscleCar('blue', '300HP'); 
  9. myCar.power; // => '300HP' 

(5) 默認(rèn)函數(shù)參數(shù)

默認(rèn)參數(shù)存在于一個(gè)中間作用域中,與全局作用域和函數(shù)作用域分離。默認(rèn)參數(shù)也遵循 TDZ 限制。

 
 
 
 
  1. const a = 2; 
  2. function square(aa = a) { 
  3.   return a * a; 
  4. // Does not work! 
  5. square(); // throws `ReferenceError` 

在聲明表達(dá)式 a = a之前,在表達(dá)式的右側(cè)使用參數(shù) a,這將生成關(guān)于 a 的引用錯(cuò)誤。

確保在聲明和初始化之后使用默認(rèn)參數(shù)。咱們可以使用一個(gè)特殊的變量 init,該變量在使用前已初始化:

 
 
 
 
  1. const init = 2; 
  2. function square(a = init) { 
  3.   return a * a; 
  4. // Works! 
  5. square(); // => 4 

3. var, function, import 語(yǔ)句

與上述陳述相反,var 和 function 定義不受 TDZ 的影響。它們被提升到當(dāng)前的作用域頂部。

如果在聲明之前訪問 var 變量,則只會(huì)得到一個(gè) undefined的變量

 
 
 
 
  1. // 正常運(yùn)行, 但不要這樣做! 
  2. value; // => undefined 
  3.  
  4. var value; 

但是,可以根據(jù)函數(shù)的定義位置來(lái)使用它:

 
 
 
 
  1. // 正常工作 
  2. greet('World'); // => 'Hello, World!' 
  3.  
  4. function greet(who) { 
  5.   return `Hello, ${who}!`; 
  6.  
  7. // 正常工作 
  8. greet('Earth'); // => 'Hello, Earth!' 

通常,咱們一般對(duì)函數(shù)的實(shí)現(xiàn)不太感興趣,而只是想調(diào)用它。因此,有時(shí)在定義函數(shù)之前先調(diào)用該函數(shù)是有意義的。

有趣的是,import 模塊也被提升了。

 
 
 
 
  1. // 正常工作 
  2. myFunction(); 
  3.  
  4. import { myFunction } from './myModule'; 

當(dāng)然,建議將 import 寫在文件開頭,以便讀寫方法。

4. TDZ 中的 typeof 行為

typeof 操作符用于確定是否在當(dāng)前作用域內(nèi)定義了變量。

例如,未定義變量 notDefined。對(duì)該變量應(yīng)用 typeof 操作符不會(huì)引發(fā)錯(cuò)誤:

 
 
 
 
  1. typeof notDefined; // => 'undefined' 

因?yàn)樽兞繘]有定義,所以 typeof notDefined 的值為 undefined。

但是 typeof 操作符在與臨時(shí)死區(qū)中的變量一起使用時(shí)具有不同的行為。在本例中,JS 拋出一個(gè)錯(cuò)誤:

 
 
 
 
  1. typeof variable; // throws `ReferenceError`  
  2. let variable; 

此引用錯(cuò)誤背后的原因是您可以靜態(tài)地(僅通過(guò)查看代碼)確定已經(jīng)定義了該變量。

5. TDZ 在當(dāng)前作用域內(nèi)采取行動(dòng)

臨時(shí)死區(qū)在聲明語(yǔ)句所在的作用域內(nèi)影響變量。

來(lái)看看例子:

 
 
 
 
  1. function doSomething(someVal) { 
  2.   // 函數(shù)作用域 
  3.   typeof variable; // => undefined 
  4.   if (someVal) { 
  5.     // 內(nèi)部塊使用域 
  6.     typeof variable; // throws `ReferenceError` 
  7.     let variable; 
  8.   } 
  9. doSomething(true); 

有 2 個(gè)作用域:

  • 函數(shù)作用域
  • 定義 let 變量的內(nèi)部塊作用域

在函數(shù)作用域中,typeof variable 的計(jì)算結(jié)果為 undefined。在這里,let 變量語(yǔ)句的 TDZ 沒有作用。

在內(nèi)部作用域中,typeof variable 語(yǔ)句在聲明之前使用一個(gè)變量,拋出一個(gè)錯(cuò)誤。ReferenceError:在初始化之前不能訪問‘variable’,TDZ 只存在于這個(gè)內(nèi)部作用域內(nèi)。

6. 總結(jié)

TDZ 是影響 const、let 和 class 語(yǔ)句可用性的重要概念。它不允許在聲明之前使用變量。

相反,可以在聲明之前使用 var 變量時(shí),var 變量會(huì)繼承較舊的行為,應(yīng)該避免這樣做。

在我看來(lái),TDZ是語(yǔ)言規(guī)范中良好的編碼實(shí)踐之一。


網(wǎng)頁(yè)標(biāo)題:知道臨時(shí)死區(qū)你才能更好的使用JS變量
當(dāng)前鏈接:http://www.5511xx.com/article/dhgdosi.html