搜尋
首頁web前端js教程5個關於JS作用域的陷阱(總結)

5個關於JS作用域的陷阱(總結)

Dec 25, 2020 pm 05:32 PM
javascript作用域

5個關於JS作用域的陷阱(總結)

在 JavaScript 中,程式碼區塊、函數或模組會為變數建立作用域。例如if 程式碼區塊為變數message 建立作用域:

if (true) {
  const message = 'Hello';
  console.log(message); // 'Hello'
}
console.log(message); // throws ReferenceError

if 程式碼區塊作用域內可以存取message。但是在作用域之外,該變數不可存取。

好的,這是作用域的簡短介紹。如果你想了解更多信息,建議閱讀我的文章用簡單的詞解釋 JavaScript 作用域

以下是 5 種有趣的情況,其中 JavaScript 作用域的行為與你預期的不同。你可能會研究這些案例以提高對作用域的了解,或只是為面試做準備。

1. for 迴圈內的var 變數

思考以下程式碼片段:

const colors = ['red', 'blue', 'white'];

for (let i = 0, var l = colors.length; i < l; i++) {
  console.log(colors[i]); // &#39;red&#39;, &#39;blue&#39;, &#39;white&#39;
}
console.log(l); // ???
console.log(i); // ???

當你列印li 變數時會發生什麼?

答案

console.log(l) 輸出數字3 ,而console.log(i ) 則拋出ReferenceError

l 變數是使用 var 語句宣告的。你可能已經知道,var 變數僅受函數體作用域限制而非程式碼區塊。

相反,變數 i 使用 let 語句宣告。因為 let 變數是區塊作用域的,所以 i 僅在 for 迴圈作用域內才可存取。

修正

l 宣告從var l = colors.length 改為const l = colors .length。現在變數 l 被封裝在 for 迴圈體內。

2. 程式碼區塊中的函數宣告

在下列程式碼片段:

// ES2015 env
{
  function hello() {
    return &#39;Hello!&#39;;
  }
}

hello(); // ???

呼叫hello() 會怎樣? (程式碼片段在ES2015 環境中執行)

答案

因為程式碼區塊為函數宣告建立了作用域,所以在ES2015 環境中呼叫hello() 會引發 ReferenceError: hello is not defined

有趣的是,在 ES2015 之前的環境中,執行上述程式碼片段時不會拋出錯誤。 你知道為什麼嗎?請在下面的評論中寫下你的答案!

3. 你可以在哪裡導入模組?

你可以在程式碼區塊中導入模組嗎?

if (true) {
  import { myFunc } from &#39;myModule&#39;; // ???
  myFunc();
}

答案

上面的腳本將觸發錯誤: 'import' and 'export' may only appear at the top-level

你只能在模組檔案的最頂級作用域(也稱為模組作用域)中導入模組。

修正

總是從模組作用域匯入模組。另外一個好的做法是將 import 語句放在原始檔的開頭:

import { myFunc } from &#39;myModule&#39;;

if (true) {
  myFunc();
}

ES2015 的模組系統是靜態的。透過分析 JavaScript 原始碼而不是執行程式碼來確定模組的依賴關係。所以在程式碼區塊或函數中不能包含 import 語句,因為它們是在執行時執行的。

4. 函數參數作用域

思考以下函數:

let p = 1;

function myFunc(p = p + 1) {
  return p;
}

myFunc(); // ???

呼叫 myFunc() 會發生什麼事?

答案

當呼叫函數myFunc() 時,將會引發錯誤: ReferenceError: Cannot access 'p' before initialization

發生這種情況是因為函數的參數具有自己的作用域(與函數作用域分開)。參數 p = p 1 等效於 let p = p 1

讓我們仔細看看 p = p 1

首先,定義變數 p。接著JavaScript 嘗試評估預設值運算式p 1,但此時綁定 p  已建立但尚未初始化(無法存取外部作用域的變數 let p = 1)。因此拋出一個錯誤,即在初始化之前訪問了 p

修復

為了解決這個問題,你可以重新命名變數let p = 1 ,也可以重新命名函數參數p = p 1

讓我們選擇重新命名函數參數:

let p = 1;

function myFunc(q = p + 1) {
  return q;
}

myFunc(); // => 2

函數參數從 p 重新命名為 q。當呼叫 myFunc() 時,未指定參數,因此將參數 q 初始化為預設值 p 1。為了評估 p 1,存取外部作用域的變數 pp 1 = 1 1 = 2

5. 函数声明与类声明

以下代码在代码块内定义了一个函数和一个类:

if (true) {
  function greet() {
    // function body
  }

  class Greeter {
    // class body
  }
}

greet();       // ???
new Greeter(); // ???

是否可以在块作用域之外访问 greetGreeter(考虑 ES2015 环境)

答案

functionclass 声明都是块作用域的。所以在代码块作用域外调用函数 greet() 和构造函数 new Greeter() 就会抛出 ReferenceError

6. 总结

必须注意 var 变量,因为它们是函数作用域的,即使是在代码块中定义的。

由于 ES2015 模块系统是静态的,因此你必须在模块作用域内使用 import 语法(以及 export)。

函数参数具有其作用域。设置默认参数值时,请确保默认表达式内的变量已经用值初始化。

在 ES2015 运行时环境中,函数和类声明是块作用域的。但是在 ES2015 之前的环境中,函数声明仅在函数作用域内。

希望这些陷阱能够帮你巩固作用域知识!

英文原文地址:https://dmitripavlutin.com/javascript-scope-gotchas/

作者:Dmitri Pavlutin

更多编程相关知识,请访问:编程入门!!

以上是5個關於JS作用域的陷阱(總結)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:segmentfault。如有侵權,請聯絡admin@php.cn刪除
JavaScript數據類型:瀏覽器和nodejs之間是否有區別?JavaScript數據類型:瀏覽器和nodejs之間是否有區別?May 14, 2025 am 12:15 AM

JavaScript核心數據類型在瀏覽器和Node.js中一致,但處理方式和額外類型有所不同。 1)全局對像在瀏覽器中為window,在Node.js中為global。 2)Node.js獨有Buffer對象,用於處理二進制數據。 3)性能和時間處理在兩者間也有差異,需根據環境調整代碼。

JavaScript評論:使用//和 / * * / * / * /JavaScript評論:使用//和 / * * / * / * /May 13, 2025 pm 03:49 PM

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python vs. JavaScript:開發人員的比較分析Python vs. JavaScript:開發人員的比較分析May 09, 2025 am 12:22 AM

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

Python vs. JavaScript:選擇合適的工具Python vs. JavaScript:選擇合適的工具May 08, 2025 am 12:10 AM

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript:了解每個的優勢Python和JavaScript:了解每個的優勢May 06, 2025 am 12:15 AM

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

JavaScript的核心:它是在C還是C上構建的?JavaScript的核心:它是在C還是C上構建的?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript應用程序:從前端到後端JavaScript應用程序:從前端到後端May 04, 2025 am 12:12 AM

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

Python vs. JavaScript:您應該學到哪種語言?Python vs. JavaScript:您應該學到哪種語言?May 03, 2025 am 12:10 AM

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具