成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

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

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

第一個創建實例,然后定義使用的類:

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

或者先于函數定義之前調用函數:

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

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

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

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

1. 什么是臨時死區

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

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

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

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

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

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

JS

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

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) 構造函數內部的 super()

如果在構造函數中調用 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` 

在構造 constructor() 中,在調用super()之前不能使用 this。

TDZ 建議調用父構造函數來初始化實例。這樣做之后,實例就準備好了,就可以在子構造函數中進行調整。

  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) 默認函數參數

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

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

在聲明表達式 a = a之前,在表達式的右側使用參數 a,這將生成關于 a 的引用錯誤。

確保在聲明和初始化之后使用默認參數。咱們可以使用一個特殊的變量 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; 

但是,可以根據函數的定義位置來使用它:

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

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

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

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

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

4. TDZ 中的 typeof 行為

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

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

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

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

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

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

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

5. TDZ 在當前作用域內采取行動

臨時死區在聲明語句所在的作用域內影響變量。

來看看例子:

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

有 2 個作用域:

  • 函數作用域
  • 定義 let 變量的內部塊作用域

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

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

6. 總結

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

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

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

責任編輯:趙寧寧 來源: 大遷世界
相關推薦

2020-11-19 07:49:24

JS變量作用域

2020-10-08 18:58:46

條件變量開發線程

2025-01-10 00:00:00

內省機制JavaBean描述器

2020-07-20 12:43:31

Go變量命名

2022-03-10 08:25:27

JavaScrip變量作用域

2021-12-29 11:38:59

JS前端沙箱

2010-03-15 14:47:19

Python內置對象

2021-11-16 08:51:29

Node JavaScript變量類型

2021-03-04 23:11:59

環境變量Python

2023-01-04 08:17:21

Typescript技巧欺騙性

2011-12-09 11:16:48

Node.js

2024-02-05 11:55:41

Next.js開發URL

2020-08-11 11:20:49

Linux命令使用技巧

2019-05-30 22:27:51

云計算成本云服務

2020-11-23 11:04:17

Redis協議緩存

2021-03-17 08:00:59

JS語言Javascript

2020-09-23 13:44:26

分類變量獨熱編碼編碼

2020-11-26 07:48:24

Shell 腳本內置

2012-09-25 13:32:31

大數據Hadoop

2024-04-09 11:40:58

DartJSWasmGC
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91午夜在线 | 91精品国产综合久久久久蜜臀 | 一区二区三区日韩精品 | 99热激情 | 91在线综合| 久久国产精品一区二区三区 | 国产97色 | 久久久精品一区 | 国产丝袜一区二区三区免费视频 | av中文在线观看 | 亚洲国产91 | 日韩免费中文字幕 | 国产夜恋视频在线观看 | 国产精品自产av一区二区三区 | 少妇精品久久久久久久久久 | 伊人狠狠干 | av一区在线观看 | 99pao成人国产永久免费视频 | www.日日干 | 国产情侣激情 | 欧美国产一区二区 | 五月婷婷激情 | 久久99精品久久 | 成人毛片在线视频 | 欧美日韩国产在线观看 | 欧美精品一区二区三区视频 | 91人人看 | 天堂在线免费视频 | 久久国产综合 | 国产一二区视频 | 久久久久久久一级 | 欧美日韩亚洲成人 | 日本久久一区二区三区 | 欧美在线一区二区三区 | 全免费a级毛片免费看视频免费下 | 国产在线一区二区三区 | 精品videossex高潮汇编 | 夜夜夜夜夜夜曰天天天 | 国产精品日韩在线 | 99在线免费观看 | 人人干人人爽 |