身為開發人員,我經常遇到「詞法環境」這個術語,但我從未真正花時間去全面深入地探索它。因此,我決定深入研究並在這篇文章中記錄我的發現 - 因為「分享就是關懷;)」。在這篇文章的結尾,我希望我們都能對詞法環境有一個深入的了解,並且我們還將探索記憶體中發生的情況、資料結構是什麼以及呼叫堆疊如何運作。別擔心 - 我會保持簡單明了!
詞彙環境
在深入了解細節之前,先簡單概述一下。如果有些概念一開始看起來很複雜,請不要擔心 - 我會將它們分解並使用類比來使它們更容易理解。
詞法環境是 JavaScript 中的一種特殊資料結構,它追蹤程式碼中特定點的變數和函數的範圍。
資料結構是一種在電腦中組織和儲存資訊以便有效使用資訊的方法。常見範例包括數組、物件、列表和樹。看更多:資料結構教學 - GeeksforGeeks
術語「詞法」意味著變數和函數的範圍和可訪問性取決於它們在程式碼中的編寫位置,而不是程式的運作方式。
詞彙環境的關鍵角色:
- 它儲存特定範圍(例如函數或區塊)內的所有變數和函數宣告。
- 它使這些儲存的項目可以在程式碼中的特定點存取。
這是一個簡單的程式碼範例,其中包含三個不同的詞法環境:
var sheep = 1; // Global sheep function drinkWater() { let waterTemperature = "cold"; console.log("The sheep is drinking " + waterTemperature + " water."); } var sheepHouseInArea = true; // Indicates whether the sheep house is present if (sheepHouseInArea) { let lambs = 2; // Lambs inside the house console.log("There are " + sheep + " sheep in the total area and " + lambs + " lambs!"); } // This will result in an error because 'lambs' // is only accessible inside the if block! console.log("How many lambs are there? " + lambs);
此程式碼中的三個詞法環境是:全域作用域、drinkWater 函數作用域和 if 區塊作用域。為了讓這些概念更容易理解,讓我們用羊做一個簡單的比喻:
羊的比喻:
本週在外面散步時,我在圍欄區域內遇到了一些羊,我想,「嘿,這就像一個詞彙環境!」
讓我解釋一下:想像一個有圍欄的區域,裡面有羊。羊隻能在圍欄內做事,例如吃草。現在,想像柵欄內有個小羊舍,小羊可以在那裡停留。屋內的羊不能出去,但屋外的羊可以進去。
打破類比:
柵欄代表一切存在的整個區域 - 綿羊、小羊、房子和草。這個圍欄區域就是我們所說的全域範圍。在這個圍欄區域內,羊舍是一個較小的、獨立的部分,代表一個街區範圍。最後,羊吃的草(yumyum)就像全局範圍內的一個函數,是羊可以在該空間內執行的特定活動或動作。
在程式碼區塊中,全域作用域以紅色框表示,drinkWater函數作用域以藍色框表示,if區塊作用域以綠色框表示。這是三個詞彙環境。
全球範圍(圍欄區域):
羊(以varsheep = 1;表示)象徵全局範圍內的變量,在圍欄區域自由漫遊。它可以在 DrinkWater 函數和 if 區塊的外部和內部使用。
功能範圍(喝水):
drinkWater 函數代表羊可以在圍欄區域內執行的動作。我們可以從全域範圍內的任何地方呼叫 DrinkWater 函數。然而,函數本身在定義時會創造一個新的詞法環境。在這個函數內部,變數(例如 let waterTemperature = 'cold';)只能在函數內部存取。
區塊範圍(如果是區塊):
if 區塊建立了一個新的、更小的作用域。在這個以羊舍為代表的範圍內,有 2 隻羔羊(設羔羊 = 2)。在此作用域內,console.log 語句記錄羔羊變數以及全域綿羊變數的值。 Lambs 變數特定於區塊作用域,而 Sheep 變數是從父環境(全域作用域)取得的。這是透過外部環境引用實現的,它允許 JavaScript 查找作用域鏈並解析當前環境中找不到的變數。
外在環境引用是詞法環境中的引用或指標。它指向父詞法環境,允許 JavaScript 透過尋找作用域鏈來解析在當前環境中找不到的變數。
提問時間!
您可以修改 DrinkWater() 函數,以便它記錄全域範圍內定義的可以喝水的羊總數嗎?在留言區分享你的答案吧!
理解多重詞彙環境
因此,我們看到這段程式碼中存在三個詞法環境:全域作用域、函數作用域和區塊作用域。當存在多個詞彙環境時,我們稱之為多個詞彙環境。理解單段程式碼中可以存在多個詞法環境非常重要。每次建立新作用域(例如,函數或區塊)時,都會產生新的詞法環境,這意味著程式碼的不同部分可以擁有自己單獨的環境。
環境記錄
現在我們了解了詞法環境的工作原理,讓我們更深入地了解環境記錄的概念。
每當建立詞法環境時 - 無論是全域範圍、函數或區塊 - JavaScript 都會自動為其產生環境記錄。
此環境記錄是一種資料結構,用於追蹤該特定範圍內可存取的所有變數、函數和其他綁定。本質上,它充當該環境中定義的所有內容的內部存儲,確保在程式碼執行期間需要時提供正確的資料。
詞彙環境和環境記錄的區別
詞法環境和環境記錄之間的主要區別:
詞法環境是 JavaScript 程式碼運作的地方。將其視為代碼所在的“設定”或“上下文”。此上下文包括變數和函數的範圍,確定哪些變數和函數在程式碼中的任何點可用或可存取。例如,在我們的程式碼中,羔羊變數只能在綠色邊框環境(區塊作用域)內存取。詞法環境還包括外部環境引用(我們已經描述過),允許存取父環境中的變數。
環境記錄是詞法環境中的特定儲存區域,它保存該環境中使用的實際變數、函數宣告和其他識別碼。雖然詞法環境是更廣泛的上下文,但環境記錄是儲存程式碼資料(例如變數值和函數定義)的位置。每當 JavaScript 需要存取變數或函數時,它都會尋找當前詞法環境的環境記錄。
讓我們使用我們的程式碼範例再次解釋一下詞法環境和環境記錄:
共有三個詞法環境,每個都有自己的環境記錄:
- 全域範圍(紅框),詞法環境 1:
這個詞彙環境是在全局層級創建的。此環境中的環境記錄包含:
- 可變的羊。
- 函數喝水。
- 變數sheepHouseInArea。
這些聲明可以在整個程式碼中存取。全域環境也引用了在此環境中定義的函數 DrinkWater 以及 if 語句,該語句在執行時會建立自己的區塊作用域。
函數範圍(drinkWater,藍色框),詞法環境 2:
此環境中的環境記錄包含變數 waterTemperature,該變數在 DrinkWater 函數中使用 let 進行宣告。該變數只能在函數內存取。然而,該函數也可以像sheep一樣存取全域環境中的變數。區塊範圍(如果是區塊,則為綠色框),詞法環境 3:
此環境中的環境記錄包含變數羔羊,在 if 區塊內使用 let 進行宣告。此變數只能在該特定區塊作用域內存取。該區塊還可以存取其父環境中的變量,例如sheep和sheepHouseInArea。
記憶中幕後發生的事情
深入研究詞法環境和環境記錄後,我們現在準備好了解 JavaScript 在程式碼執行期間如何管理記憶體和變數存取。
當您的程式碼執行時,JavaScript 會為每個函數或程式碼區塊建立一個新的詞法環境。每個環境都有自己的環境記錄,儲存在該範圍內定義的所有變數和函數。正如我們所討論的,此設定可確保高效的記憶體使用。
Behind the scenes, the JavaScript engine handles these lexical environments in memory. The call stack is used for tracking function calls, while block scopes create new lexical environments linked to their outer environments. However, unlike functions, these block scopes aren't pushed onto the call stack.
What is the call stack?
The call stack is a fundamental concept in how Javascript executes code.
The call stack is a data structure that keeps track of function calls in a program. It works on a Last-In-First-Out (LIFO) principle. Here's how it works:
- When a function is called, it's added (pushed) to the top of the stack.
- When a function finishes executing, it's removed (popped) from the top of the stack.
- The stack also keeps track of the current position in the code.
Key points about the call stack:
- It records where in the program we are.
- If we step into a function, we put it on the top of the stack.
- If we return from a function, we pop it off the stack.
- The stack has a maximum size, and if that limit is exceeded, it results in a "stack overflow" error.
Now you know why its called stack overflow haha!
Here's a simple example to illustrate:
function greet(name) { console.log('Hello, ' + name); } function processUser(user) { greet(user); } processUser('Alice');
- main() (global execution context)
- processUser('Alice')
- greet('Alice')
As each function completes, it's popped off the stack until we return to the global context.
The last final question!
In our sheep code example, can you identify if anything is placed on the call stack during execution? Share your thoughts in the comments section!
Conclusion
That's it for Part 1! I hope this post has helped you gain a solid understanding of how JavaScript handles lexical environments, environment records, and what happens behind the scenes in memory. I've learned a lot in the process, and I hope you have too. If you have any questions or feedback, I'd love to hear from you - let's learn and improve together!
I titled this post 'Part 1' because I plan to follow up with 'Part 2,' where I'll dive into three major concepts that are closely linked to lexical environments:
- Closures: Think of them as magical boxes that let functions remember and access variables from their outer environment, even after the outer function has finished executing.
- Scope Chains: We'll explore how JavaScript navigates through nested environments to find variables, like a treasure hunt in your code.
- Hoisting: This explains why some variables and functions seem to "float" to the top of their scope, which can be tricky to understand but is crucial for writing predictable code.
These concepts are super important because they directly impact how your JavaScript code behaves. Understanding them will help you write cleaner, more efficient code and avoid some common pitfalls.
Stay tuned!
--
Please also follow me on my Medium: https://medium.com/@ensing89
以上是JS — 理解 JavaScript 中的詞法環境 — 深入探究 — 第 1 部分的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

本教程向您展示瞭如何將自定義的Google搜索API集成到您的博客或網站中,提供了比標準WordPress主題搜索功能更精緻的搜索體驗。 令人驚訝的是簡單!您將能夠將搜索限制為Y

因此,在這裡,您準備好了解所有稱為Ajax的東西。但是,到底是什麼? AJAX一詞是指用於創建動態,交互式Web內容的一系列寬鬆的技術。 Ajax一詞,最初由Jesse J創造

本文系列在2017年中期進行了最新信息和新示例。 在此JSON示例中,我們將研究如何使用JSON格式將簡單值存儲在文件中。 使用鍵值對符號,我們可以存儲任何類型的

增強您的代碼演示文稿:10個語法熒光筆針對開發人員在您的網站或博客上共享代碼段的開發人員是開發人員的常見實踐。 選擇合適的語法熒光筆可以顯著提高可讀性和視覺吸引力。 t

本文介紹了關於JavaScript和JQuery模型視圖控制器(MVC)框架的10多個教程的精選選擇,非常適合在新的一年中提高您的網絡開發技能。 這些教程涵蓋了來自Foundatio的一系列主題

利用輕鬆的網頁佈局:8 ESTISSEL插件jQuery大大簡化了網頁佈局。 本文重點介紹了簡化該過程的八個功能強大的JQuery插件,對於手動網站創建特別有用

核心要點 JavaScript 中的 this 通常指代“擁有”該方法的對象,但具體取決於函數的調用方式。 沒有當前對象時,this 指代全局對象。在 Web 瀏覽器中,它由 window 表示。 調用函數時,this 保持全局對象;但調用對象構造函數或其任何方法時,this 指代對象的實例。 可以使用 call()、apply() 和 bind() 等方法更改 this 的上下文。這些方法使用給定的 this 值和參數調用函數。 JavaScript 是一門優秀的編程語言。幾年前,這句話可


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

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

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

SublimeText3 Linux新版
SublimeText3 Linux最新版