自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

知道臨時死區(qū)你才能更好的使用 JS 變量

開發(fā) 前端
TDZ 是影響 const、let 和 class 語句可用性的重要概念。它不允許在聲明之前使用變量。相反,可以在聲明之前使用 var 變量時,var 變量會繼承較舊的行為,應該避免這樣做。

首先,來個一個簡單的問題。下列哪段代碼會產(chǎn)生錯誤:

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

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

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

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

正確的答案是:第一個代碼片段會報 ReferenceError: Cannot access 'Car' before initialization 錯誤。第二個代碼正常運行。

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

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

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

咱們先從一個簡單的 const 變量聲明開始。首先聲明并初始化變量,然后訪問它,一切正常運行:

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

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

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

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

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

JS

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

2. 受 TDZ 影響的聲明

來看看受 TDZ 影響的聲明。

(1) const變量

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

  1. // 無法工作 
  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 聲明語句也會受到 TDZ 的影響:

  1. // 無法工作 
  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. // 無法工作 
  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()之前擴展父類,則此綁定位于 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ù)來初始化實例。這樣做之后,實例就準備好了,就可以在子構(gòu)造函數(shù)中進行調(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) 默認函數(shù)參數(shù)

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

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

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

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

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

3. var, function, import 語句

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

如果在聲明之前訪問 var 變量,則只會得到一個 undefined的變量

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

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

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

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

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

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

當然,建議將 import 寫在文件開頭,以便讀寫方法。

4. TDZ 中的 typeof 行為

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

例如,未定義變量 notDefined。對該變量應用 typeof 操作符不會引發(fā)錯誤:

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

因為變量沒有定義,所以 typeof notDefined 的值為 undefined。

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

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

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

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

臨時死區(qū)在聲明語句所在的作用域內(nè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 個作用域:

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

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

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

6. 總結(jié)

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

相反,可以在聲明之前使用 var 變量時,var 變量會繼承較舊的行為,應該避免這樣做。

在我看來,TDZ是語言規(guī)范中良好的編碼實踐之一。

責任編輯:趙寧寧 來源: 大遷世界
相關(guān)推薦

2020-11-19 07:49:24

JS變量作用域

2020-10-08 18:58:46

條件變量開發(fā)線程

2020-07-20 12:43:31

Go變量命名

2025-01-10 00:00:00

內(nèi)省機制JavaBean描述器

2022-03-10 08:25:27

JavaScrip變量作用域

2021-12-29 11:38:59

JS前端沙箱

2010-03-15 14:47:19

Python內(nèi)置對象

2021-11-16 08:51:29

Node JavaScript變量類型

2023-01-04 08:17:21

Typescript技巧欺騙性

2024-02-05 11:55:41

Next.js開發(fā)URL

2021-03-04 23:11:59

環(huán)境變量Python

2020-11-23 11:04:17

Redis協(xié)議緩存

2020-09-23 13:44:26

分類變量獨熱編碼編碼

2021-03-17 08:00:59

JS語言Javascript

2011-12-09 11:16:48

Node.js

2019-05-30 22:27:51

云計算成本云服務

2020-08-11 11:20:49

Linux命令使用技巧

2012-09-25 13:32:31

大數(shù)據(jù)Hadoop

2020-11-26 07:48:24

Shell 腳本內(nèi)置

2023-10-30 11:53:37

繼承JS父類
點贊
收藏

51CTO技術(shù)棧公眾號