首頁  >  文章  >  web前端  >  理解 JavaScript 中的作用域

理解 JavaScript 中的作用域

WBOY
WBOY原創
2024-08-18 08:39:32898瀏覽

Understanding scope in JavaScript

這個主題已經被討論過很多次了,不過,我還是想從它要解決的問題的角度來談談什麼是作用域(使用 JavaScript)。

範圍實際上解決了什麼問題?

隨著應用程式規模的增加,它們的複雜性也會增加 - 範圍是管理這種複雜性的工具。

耦合與解耦

假設我們有一個設定為 7 的全域變數 radius 和一個傳回「特殊」按鈕的函數 createSpecialButton():

雷雷

此函數傳回一個具有特定半徑的按鈕,在本例中設定為 7。現在,程式碼沒有問題,因為我們知道半徑設定為多少,因此知道生成的按鈕會是什麼樣子。但是,如果我們添加兩個都依賴半徑變數的函數,會發生什麼情況呢?我們的程式碼現在看起來像這樣:

雷雷

進行此變更後,呼叫 createSpecialButton() 時半徑的值會是多少?如果你猜對了 16,那就對了。

僅僅透過添加兩個附加函數,我們就大大增加了程式碼的複雜性,現在生活在一個多個不相關的程式碼片段依賴於相同依賴項的世界。現在,想像這是一個更大的全端應用程式 - 很快就會變得很難推斷某些狀態部分來自何處以及如何在出現錯誤時修復它們。

為了解決這個問題,我們可以為每個函數定義一個單獨的半徑變數:

雷雷

您可能會看到此更改並說“好吧,好吧,但現在有更多代碼 - 這似乎不對”。沒錯,程式碼更多,但是程式碼越少也不是更好,如果它會導致程式碼的可維護性降低 - 我們所做的更改提高了程式碼的可維護性,這總是一件好事。

JavaScript 中的作用域類型

全球範圍

整個應用程式中的所有內容都可以存取全域範圍。如果您正在編寫 Node.JS 應用程序,您可能不會使用或遇到全域範圍。但是,如果您在 Web 應用程式中工作,則可以使用腳本標記或使用 window.SOMETHING.

將聲明置於全域範圍內

例如,使用 script 標籤,你可能會這樣做:


雷雷

此外,MDN 將「全域作用域」的定義表述為「在腳本模式下執行的所有程式碼的預設作用域」。我

認為上面的例子就是他們所指的。

使用 window 全域物件時,你可能會這樣做:


雷雷

模組範圍

如果您在 Node.JS 專案中工作,那麼模組範圍是您將在最高級別上使用的範圍。每個帶有 .js (或 .ts)副檔名的檔案都是一個單獨的模組,這意味著給定檔案中的所有內容最多都可以存取您的聲明,除非您明確匯出它們。

例如,在user.ts中,兩個函數都可以存取變數名稱。


雷雷

但是,在這個版本的 user.ts 中,只有 accessName() 可以存取變數名稱:


雷雷

請注意,在這兩個模組中,都沒有導出任何內容。換句話說,其他模組中的程式碼無法知道該程式碼,因此無法匯入和使用它。但我們可以改變這一點:


雷雷

現在,這兩個函數都已匯出,因此可以被其他模組使用。這在技術上與我們之前討論的全局範圍的概念不同,但相似之處在於我們透過將程式碼從一個模組導入到另一個模組來使程式碼可供整個應用程式使用。

功能範圍

我們其實已經了解函數作用域了。請參閱下面的程式碼(與上面的程式碼片段之一相同):


雷雷

嘗試執行這個 -greetAgain() 會遇到錯誤,因為它嘗試讀取的名稱變數只存在於greet()的上下文(即「範圍」)內。

注意:您可能會看到這被稱為“本地範圍”。

區塊範圍

塊作用域是一個有趣的作用域,因為它只適用於較新的變數類型 - 具體來說,let 和 const,而不是 var。我們來看看吧。


雷雷

在上面的範例中,我們可以看到 1) 將程式碼放置在 {} 中會建立一個程式碼區塊。 2)使用let和const定義的變數只能在該程式碼區塊內存取。 3)用var建立的變數不遵循區塊作用域的規則,因為它仍然可以在{}之外存取。

注意:現代 JavaScript 使用 let 和 const 來宣告變數,而不是 var。

聲明應在必要的最小範圍內作出

最後,請記住,作用域是管理程式碼複雜性的工具,放置聲明的作用域層級越高,程式碼的複雜度就越高,因此最好將聲明放在一起在必要的最小範圍內。

以上是理解 JavaScript 中的作用域的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn