JavaScript 的底層是如何運作的?
這篇文章的真正目的是以一種簡單的方式介紹 JavaScript 在底層如何工作,這樣即使是新程式設計師也能夠掌握這個概念並可視化編寫 JavaScript 時會發生什麼。
首先,我想專注於至少 3 個問題,這將有助於克服困難並內化背後的邏輯?
這些問題也是 Web 開發人員在面試時可能會被問到的問題,其中 JavaScript 意味著:
1。 JavaScript 是如何運作的?
2.解釋一下同步和非同步的差別?
3.或解釋這句話:JavaScript是單執行緒語言,可以是非阻塞的?
確實,編寫程式並不需要知道JavaScript 內部是如何運作的,但是為了理解背後發生的事情並感受你正在編寫的內容,學習JavaScript 是必要且至關重要的,因此對於許多擁有多年經驗的開發人員來說營運商不想知道這一點。
讓我們先知道什麼是程式? 程式只是一組指令,告訴電腦要做什麼以及如何執行任務。程式必須分配記憶體,否則,我們將無法在電腦上擁有變量,甚至無法儲存檔案。程式還應該解析(讀取)並執行專用任務,並且所有操作都發生在記憶體中。
現在,JavaScript 擁有每個瀏覽器都實作的名為 JavaScript 引擎 的引擎。例如,在 Chrome 中,它稱為 V8,在 Mozilla Firefox 中:Spider Monkey,Safari 瀏覽器:JavaScript Core Webkit。
下圖為 google chrome 的 V8 引擎
JavaScript 引擎內部發生了什麼事?
JavaScript 引擎(例如 Chrome 中的 V8)讀取我們編寫的 JavaScript 程式碼,並將其轉換為瀏覽器的機器執行指令。上圖顯示了 JavaScript 引擎的各個部分,它由兩部分組成,即內存堆**和**調用堆疊。
還要注意的是,記憶體分配發生在記憶體堆中,而解析(讀取)和執行發生在呼叫堆疊中。除此之外,記憶體堆告訴你你在程式中的位置。
讓我們用 JS (JavaScript) 程式碼看看記憶體堆中的記憶體分配
const a = 4; // now we allocated a memory. JS engine is going to remember // that a has a value of 4. const Obj = {a, b, c }; // In memory, variable 'Obj' holds the object {a, b,c} // The same as on array. the engine will remember values of the array const Array = [1,2,3,4,5]
那麼,上述程式碼在全域宣告後會出現什麼問題呢?
有一種叫做記憶體洩漏的東西。如上所述,變數聲明發生在記憶體堆中,並且它的分配大小是有限的。當您繼續聲明非常大的陣列而不是數字甚至未使用的全域變數時,這會填滿記憶體並導致記憶體洩漏。你會聽到全域變數很糟糕,因為當我們忘記清理時,我們會填滿這個記憶體堆,最終瀏覽器將無法運作。
呼叫堆疊怎麼樣?
如果我們還記得的話,讀取和執行腳本的是呼叫堆疊。我們用程式碼來說明一下吧。
const a = 4; // now we allocated a memory. JS engine is going to remember // that a has a value of 4. const Obj = {a, b, c }; // In memory, variable 'Obj' holds the object {a, b,c} // The same as on array. the engine will remember values of the array const Array = [1,2,3,4,5]
透過上面的程式碼,呼叫sack讀取第一行console.log(“x”);並被放入呼叫堆疊中,JavaScript引擎辨識出console. log已被添加,然後將其彈出到調用堆疊中,運行它,並輸出x。之後,它會刪除第一個console.log,因為它已完成運行,並將其放入第二個console.log(“y”),將其添加到呼叫堆疊中,執行y 並刪除第二個console.log。最後使用相同的過程取得console.log(“z”)。
這是最簡單的演示,如果再複雜一點怎麼辦?舉個典型的例子:
// Example Call Stak console.log("x"); console.log("y"); console.log("z"); // Result in browser // x // y // z
//呼叫堆疊
函數example1() 將首先運行,然後函數example2() 出現在調用堆疊的頂部並運行,在檢查是否存在後打印出數字7 作為輸出其他要運行的程式碼。之後,它將開始按從 console.log(‘7’)、example2()、example1() 開始的順序從呼叫堆疊中刪除,並且呼叫堆疊現在為空。
>我們還記得這句話嗎? JavaScript 是一種非阻塞的單執行緒語言。
單執行緒意味著它只有一個呼叫堆疊。它一次只能執行一件事,需要強調的是呼叫堆疊是先進後出的,就像堆疊。
其他語言可以有許多呼叫堆疊,也就是所謂的多執行緒,擁有多個呼叫堆疊可能更有利,這樣我們就不必一直等待任務。
>但是,為什麼 JavaScript 被設計為單執行緒呢?
要回答這個問題,通常在單執行緒上執行程式碼非常容易,因為多執行緒環境中不會出現複雜的場景。你實際上有一件事情需要關心。在多執行緒中,可能會出現死鎖之類的問題。有了這個理論,我們很容易知道同步程式設計意味著什麼。
同步程式簡單來說就是:執行第一行程式碼,執行第二行程式碼,執行第三行程式碼,等等......
更明確地說,這意味著console.log(“y”) 無法運行,直到console.log(“x”) 完成並且console. log (“z”) 直到前兩個都完成後才開始,因為它是一個 呼叫堆疊。
程式設計師很可能會使用 stackoverflow.com 網站。這個名字是什麼意思?出色地。讓我們來看看:
堆疊溢位是如何發生的
上圖顯示了記憶體洩漏是如何發生的以及 JavaScript 引擎的記憶體堆如何溢出。這裡,呼叫堆疊接收許多大於其大小的輸入並溢出。
可以藉助程式碼來示範堆疊溢位:
const a = 4; // now we allocated a memory. JS engine is going to remember // that a has a value of 4. const Obj = {a, b, c }; // In memory, variable 'Obj' holds the object {a, b,c} // The same as on array. the engine will remember values of the array const Array = [1,2,3,4,5]
請注意,JavaScript 是單執行緒的,一次只執行一個語句。 現在有一個問題:如果下面程式碼區塊中的console.log(“y”)有一個需要更長時間才能完成的大任務怎麼辦?例如循環遍歷具有數千或數百萬項的數組?那裡會發生什麼事?
// Example Call Stak console.log("x"); console.log("y"); console.log("z"); // Result in browser // x // y // z
第一行將執行,並假設第二行有大量工作要執行,因此第三行將等待很長時間才能執行。在上面的範例中,這沒有多大意義,但讓我們想像一個執行繁重操作的大型網站,用戶將無法執行任何操作。網站將凍結,直到任務完成並且用戶在那裡等待。對於表演來說這是一次糟糕的體驗。
嗯,對於同步任務,如果我們有一個函數需要花費很多時間,那麼它就會阻塞隊列。所以,聽起來我們需要一些非阻塞的東西。請記住我上面提到的那句話:JavaScript 是一種可以非阻塞的單執行緒語言。
理想情況下,在 JavaScript 中我們不會等待需要時間的事情。那麼,我們該如何解決這個問題呢?
作為救援,有非同步程式設計。那麼,這是什麼?
將非同步視為一種行為。同步執行很棒,因為它是可預測的。在同步中,我們知道首先發生什麼,接下來發生什麼等等,但它可能會變慢。
當我們必須執行影像處理或透過網路發出請求(例如 API 呼叫)等操作時,我們使用的不僅僅是非同步同步任務。
讓我們來看看如何用程式碼進行非同步程式設計:
const a = 4; // now we allocated a memory. JS engine is going to remember // that a has a value of 4. const Obj = {a, b, c }; // In memory, variable 'Obj' holds the object {a, b,c} // The same as on array. the engine will remember values of the array const Array = [1,2,3,4,5]
現在,根據上面的程式碼,我們似乎跳過了第二行並執行第三行,並等待 3 秒輸出結果。這是異步發生的。
為了理解這一點以及發生了什麼,讓我們使用下圖。
JavaScript 執行環境
為了運行 JavaScript,我們需要的不只是記憶體堆和呼叫堆疊。我們需要所謂的 JavaScript Run-Time,它是瀏覽器的一部分。它包含在瀏覽器中。在引擎之上,有一些稱為Web API,回調隊列和事件循環,如圖所示。
現在我們來討論一下使用 setTimeout 函數的程式碼。
// Example Call Stak console.log("x"); console.log("y"); console.log("z"); // Result in browser // x // y // z
setTimeout 函數 是 Web API 的一部分,而不是 JavaScript 的一部分,相反,它是瀏覽器提供給我們用來進行非同步程式設計的函數。因此,讓我們提供更多詳細資訊以進行澄清。
呼叫堆疊: console.log(“x”) 進入呼叫堆疊,運行,然後我們將 console.log 傳送到瀏覽器。之後,setTimeout(() =>{console.log(“y”);},3000);進入呼叫堆疊,因為第一個任務完成,然後轉到第二個任務。
現在有件事,在閱讀程式碼時,呼叫堆疊會偵測到有一個setTimeout 函數 已被設置,它不是JavaScript 的一部分,而是Web API 的一部分(參見圖JavaScript 執行時間環境)並具有其特殊的特性。發生的情況是 setTimeout 觸發 WEB API 並且由於 Web API 收到通知,該函數將從呼叫堆疊中彈出。
現在,Web API 啟動一個三秒的計時器,知道它必須在 3 秒內完成任務。請記住這裡,因為呼叫堆疊是空的,JavaScript 引擎繼續到第 3 行,即 console.log(“z”);並執行它。這就是為什麼我們得到結果 x,z 但我們在 Web API 中設定了三秒鐘的 setTimeout。然後,三秒鐘後,當時間限制結束時,setTimeout 運行並查看其中的內容,然後就完成了。完成後,Web API 將識別出它有 setTimeout 的 callback() 函數,並將其添加到 CALLBACK QUEUE 準備運行它。
我們來到最後一部分,即**事件循環*。這個函數會一直檢查呼叫堆疊是否為空。當它為空並且JavaScript 引擎中目前沒有運行任何內容時,它將檢查回調隊列並使用console.log(“z”) 找到我們的**callback()* 函數,然後將其放入CALL STACK 並運行。完成後,將其從呼叫堆疊中彈出。現在一切都是空的並且得到結果 x z y。
結論:在這篇文章中,我們看到了很多有關幕後發生的事情的信息,以完全理解 JavaScript 邏輯以及同步和異步執行的任務。
希望這將有助於新的和高級 JavaScript 程式設計師享受在 ReactJS 或 AngularJS 等 JavaScript 相關框架中進行編碼,因為這是理解高級邏輯的基礎。
>快樂編碼
參考文獻
https://www.freecodecamp.org/news/how-javascript-works-behind-the-scenes。
https://www.simplilearn.com/tutorials/javascript-tutorial/callback-function-in-javascript#
以上是JavaScript 的底層是如何運作的?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。
