您現在的位置是:首頁 > 足球

JavaScript到底是解釋型語言還是編譯型語言?

  • 由 這個世界很Cool 發表于 足球
  • 2022-03-22
簡介解釋型語言也是人類可以理解的語言(程式語言),也需要轉換成機器可以理解的語言才能執行,但是是在執行時轉換的

什麼叫解釋型語言

前言

最開始的時候,JavaScript的聖經——MDN明確地說JavaScript是一個解釋型語言(同時還說到了及時編譯,後面我會強調這一點)。但是下面幾點仍然會讓JavaScript是否真的是一個解釋型語言產生疑問:

如果是解釋型語言那麼宣告提升為什麼會發生

JIT(及時編譯)做程式碼最佳化(同時生成編譯版本);解釋型語言無法做到這些。

JavaScript到底是解釋型語言還是編譯型語言?

編譯型語言 VS 解釋型語言

主要問題是沒有團體或者組織規定這些;例如:編譯型語言和解釋型語言的定義以及如何劃分。 而這兩個都是概念。

所以根據概念,編譯型語言是程式碼在執行前編譯器將人類可以理解的語言(程式語言)轉換成機器可以理解的語言。

解釋型語言也是人類可以理解的語言(程式語言),也需要轉換成機器可以理解的語言才能執行,但是是在執行時轉換的。所以執行前需要直譯器安裝在環境中;但是編譯型語言編寫的應用在編譯後能直接執行。

許多人認為解釋型語言意味著當遇到程式中行號為xyz時直接將其傳給CPU就能執行;但是事實不是這樣。所有的程式語言都是為人類建立的。他們是人類能夠理解的。你必須將程式語言轉換為機器語言。編譯器獲取整個程式碼,轉換它,做合適的最佳化並且建立一個可以執行的輸出檔案。編譯器根據上下文來轉換語句。

宣告提升

在函式作用域內的任何變數的宣告都會被提升到頂部並且是undeinfed值。下面是JavaScript處理宣告的過程:

一旦V8引擎進入一個執行具體程式碼的執行上下文(函式),它就對程式碼進行詞法分析或者分詞。這意味著程式碼將被分割成像foo = 10這樣的原子標記。

在對當前的整個作用域分析完成後,引擎將解析成一個AST(抽象語法書)的翻譯版本。

引擎每一次遇到宣告,它就把宣告傳到作用域來建立一個繫結。對每一次宣告它都會為變數分配記憶體。只是分配記憶體而不是把程式碼修改成宣告提升。正如你所知道的,在JS中分配記憶體意味著將預設值設為undefined。

在這之後,引擎每一次遇到賦值或者取值,它都會透過作用域查詢繫結。如果在當前作用域中沒有查詢到就接著向上級作用域查詢直到找到為止。

接著引擎生成CPU可以執行的機器碼。

最後, 程式碼執行完畢。

所以變數提升不過是執行上下文的遊戲,而不是網站描述的程式碼修改。在執行任何語句之前,直譯器就已經從執行上下文建立的作用域中找到變數的值了。

JavaScript中的即時編譯

編譯型和解釋型語言最重要的區別是編譯語言話很長的時間來準備執行。因為它需要對整個程式碼進行詞法分析、做一些極致的最佳化等工作。另一方面解釋型語言幾乎在執行後一瞬間就開始,但是沒有任何程式碼最佳化。所以沒一條語句都是分開轉換的,看下面這一段程式碼:

JavaScript到底是解釋型語言還是編譯型語言?

在編譯型語言中sum += i部分在迴圈執行時已經編譯成了機器碼,機器碼將直接執行一千次。

但是在解釋型語言中,他會在執行時將sum += i解釋一千次。所以因為對相同的程式碼進行一千次轉換會造成非常大的效能損耗。

總結

JavaScript程式碼需要在機器(node或者瀏覽器)上安裝一個工具(JS引擎)才能執行。這是解釋型語言需要的。編譯型語言產品能夠自由地直接執行。

宣告提升等不是程式碼修改。在這個過程中沒有生成中間程式碼。這只是JS直譯器處理事情的方式。

即時編譯是唯一一點我們可以對JavaScript是否是一個解釋型語言提出疑問的理由。但是即時編譯不是純粹的編譯器,它在執行前進行編譯。而且JIT知識Mozilla和Google的開發人員為了在他們的瀏覽器產品中提升效能才引入的。JavaScript或TC39從來沒有要求這樣做。

因此,雖然JavaScript執行時像是編譯過的或者是一種混合,但是我覺得說JavaScript是一個解釋型語言要好過說是一個編譯型語言或者最近很多人說的一個混合型的語言。各位小夥伴,你們覺得呢?

Top