摘要:編譯型語言解釋型語言主要問題是沒有團體或者組織規定這些例如編譯型語言和解釋型語言的定義以及如何劃分。下面是處理聲明語句的過程一旦引擎進入一個執行具體代碼的執行上下文函數,它就對代碼進行詞法分析或者分詞。這是解釋型語言需要的。
幾天前一個剛接觸 JavaScript 的朋友問我 JavaScript 是編譯型語言還是解釋型語言。從一個初學者那里聽到這樣的問題讓我有些驚訝,因為所有初學者都知道 JS 是一個解釋型語言;特別是像她這樣之前使用過 Java 這類語言的初學者。
當一些人深入 JavaScript 并且開始研究 V8 引擎、SpiderMonkey、JIT 之類東西的時候,他們開始對于解釋型還是編譯型有更多的疑問。很高興看到她已經在這個階段了。
令人困惑的是什么?最開始的時候,JavaScript 的圣經 —— MDN 明確地說 JavaScript 是一個解釋型語言(同時還說到了 JIT 及時編譯,后文會提及)。但是下面幾點仍然會讓 JavaScript 是否真的是一個解釋型語言產生疑問:
如果 JS 是解釋型語言那為什么會有變量提升(hoisting)?
JIT(及時編譯)會做代碼優化(同時創建代碼的編譯版本);解釋型語言無法做到這些。
有什么快速的回答嗎?由于 JavaScript 規范沒有對這一點做明確說明,困惑和疑問是都是存在的,不能片面地回答。讓我們基于理論定義和 JavaScript 工作流程來弄清楚 JavaScript 到底是什么語言。
編譯型語言 VS 解釋型語言主要問題是沒有團體或者組織規定這些;例如:編譯型語言和解釋型語言的定義以及如何劃分。 而這兩個都是概念。
所以根據概念,編譯型語言是代碼在運行前編譯器將人類可以理解的語言(編程語言)轉換成機器可以理解的語言。
解釋型語言也是人類可以理解的語言(編程語言),也需要轉換成機器可以理解的語言才能執行,但是是在運行時轉換的。所以執行前需要環境中安裝了解釋器;但是編譯型語言編寫的應用在編譯后能直接運行。
許多人認為解釋型語言意味著當遇到程序中行號為xyz時直接將其傳給CPU就能運行;但是事實不是這樣。所有的編程語言都是為人類創建的。他們是人類能夠理解的。必須將編程語言轉換為機器語言才能運行。編譯器獲取整個代碼,轉換它,做合適的優化并且創建一個可以運行的輸出文件。編譯器根據上下文來轉換語句。
那么變量提升呢?我覺得你應該已經知道了 JavaScript 的變量提升。在函數作用域內的任何變量的聲明都會被提升到頂部并且值為undeinfed。
所以 JavaScript 引擎好像解釋了同一個腳本文件兩次?第一次完成所有的聲明提升然后第二次才執行代碼?還是先編譯整個代碼然后運行它?這兩種都不對。
下面是 JavaScript 處理聲明語句的過程:
一旦 V8 引擎進入一個執行具體代碼的執行上下文(函數),它就對代碼進行詞法分析或者分詞。這意味著代碼將被分割成像foo = 10這樣的原子符號(atomic token)。
在對當前的整個作用域分析完成后,引擎將 token 解析翻譯成一個AST(抽象語法樹)。
引擎每次遇到聲明語句,就會把聲明傳到作用域(scope)中創建一個綁定。每次聲明都會為變量分配內存。只是分配內存,并不會修改源代碼將變量聲明語句提升。正如你所知道的,在JS中分配內存意味著將變量默認設為undefined。
在這之后,引擎每一次遇到賦值或者取值,都會通過作用域(scope)查找綁定。如果在當前作用域中沒有查找到就接著向上級作用域查找直到找到為止。
接著引擎生成 CPU 可以執行的機器碼。
最后, 代碼執行完畢。
所以變量提升不過是執行上下文的小把戲,而不是許多網站描述的源代碼修改。在執行任何語句之前,解釋器就要從創建執行上下文后已經存在的作用域(scope)中找到變量的值。
解釋 JavaScript 中的即時編譯(JIT)JIT 或 及時編譯 編譯器不是 JavaScript 所特有的。其他語言比如 Java 也有一些在執行前編譯代碼的機制。
現代 JavaScript 引擎同樣有 JIT。是的,它們有編譯器。讓我來為你解釋一下為什么它們需要 JIT 以及 JIT 在 JavaScript 的執行中是如何工作的。
編譯型和解釋型語言最重要的區別是編譯型語言需要很長的時間來準備執行。因為它需要對整個代碼進行詞法分析、做一些極致的優化等工作。另一方面解釋型語言幾乎在執行后一瞬間就開始,但是沒有任何代碼優化。所以每一條語句都是分開轉換(編譯)的,考慮下面這一段代碼。
for(i=0; i < 1000; i++){ sum += i; }
在編譯型語言中sum += i部分在循環運行時已經編譯成了機器碼,機器碼將直接運行一千次。
但是在解釋型語言中,執行時會將sum += i轉換(編譯)一千次。對相同的代碼進行一千次轉換會造成非常大的性能損耗。
這就是 Google 和 Mozilla 的開發人員將 JIT 加入 JavaScript 的原因。
編譯在 JavaScript 中如果一段代碼運行超過一次,那么就稱為 warm。如果一個函數開始變得 warmer(譯者注:即運行更多次),JIT 將把這段代碼送到編譯器中編譯并且保存一個編譯后的版本。下一次同樣代碼執行的時候,引擎會跳過翻譯過程直接使用編譯后的版本。
這將優化性能。在真正的編譯器中,因為編譯器能訪問整個代碼所以做了除此之外更多的事情。
優化如果一段 warm 的代碼變得 hot 或者 hotter(譯者注:指運行更多次以及比更多還要多的次數)JIT 會嘗試更多的優化并且保存優化后的版本。在編譯器進行優化的過程中會做一些關于變量類型和運行環境中值的假設,如果假設不成立就將這個優化的版本回退,如果假設成立的話,這將讓代碼性能更高。
想要了解更多 JIT 的知識可以閱讀 Lin Clarks 關于JIT的課程。
總結現在我們了解了 JavaScript 執行時到底發生了什么,所以應該可以區分 JavaScript 到底是編譯型還是解釋型語言了。下面是這篇文章的要點。
JavaScript 代碼需要在機器(node 或者瀏覽器)上安裝一個工具(JS 引擎)才能執行。這是解釋型語言需要的。編譯型語言程序能夠自由地直接運行。
變量提升不是代碼修改。在這個過程中沒有生成中間代碼。變量提升只是 JS 解釋器處理事情的方式。
JIT 是唯一一點我們可以對 JavaScript 是否是一個解釋型語言提出疑問的理由。但是 JIT 不是完整的編譯器,它在執行前進行編譯。而且 JIT 只是 Mozilla 和 Google 的開發人員為了提升瀏覽器性能才引入的。JavaScript 或 TC39 從來沒有強制要求使用 JIT。
因此,雖然 JavaScript 執行時像是在編譯或者像是一種編譯和解釋的混合,我仍然認為 JavaScript 是一個解釋型語言或者是一個今天很多人說的混合型語言,而不是編譯型語言。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107210.html
摘要:編譯型語言把做好的源程序全部編譯成二進制代碼的可運行程序。所以可是說即是編譯型的,也是解釋型,但是假如非要歸類的話,從概念上的定義,恐怕應該歸到解釋型的語言中。編譯型的語言包括解釋型的語言包括 轉載自網絡 Java這個語言很神奇: 你可以說它是編譯型的。因為所有的Java代碼都是要編譯的,.java不經過編譯就什么用都沒有。 你可以說它是解釋型的。因為java代碼編譯后不能直接運行,...
摘要:最后給出編譯型語言和解釋型語言的定義。定義編譯型語言把做好的源程序全部編譯成二進制代碼的可運行程序。解釋型語言把做好的源程序翻譯一句,然后執行一句,直至結束特點編譯型語言,執行速度快效率高依靠編譯器跨平臺性差。 有人說Java是編譯型的。因為所有的Java代碼都是要編譯的,.java不經過編譯就無法執行。 也有人說Java是解釋型的。因為java代碼編譯后不能直接運行,它是解釋運行在J...
摘要:可以脫離語言環境獨立運行就像一本英文書,我找一個翻譯,給他點時間,把英文書翻譯成中文的,這就是編譯型語言解釋型語言有良好的平臺兼容性,在任何環境中都可以運行,前提是安裝了解釋器虛擬機。就像還是一本英文書,我看一句讓他給我解釋一句。 寫在前面 隨著大數據、人工智能這類詞匯撲向我們,python這個早在1989就已經出現的語言終于高調回歸,為了更好的學習python 我們先來了解下它的前世...
摘要:函數式編程最后介紹一下函數式編程。函數式編程是一種歷史悠久,而又在最近頗為熱門的話題。函數式編程在面向對象一詞誕生以前就已經存在,不過它在很長一段時間里都被隱藏于過程式編程面向對象也是過程式編程的一種的概念之下。 2.1 JavaScript特點 總結以下幾個特點: 解釋型語言 類似與C和Java的語法結構 動態語言 基于原型的面向對象 字面量的表現能力 函數式編程 解釋型語言:...
摘要:準確的理解,是編譯型語言,源代碼整個編譯成字節碼,字節碼,是解釋型語言。是一個非常靈活的語言,支持命令式和函數式編程。編譯型語言通常會用做配置文件,因為我們通常不會改編譯后的字節碼。 編程語言按各種方法可以分為各種類型,現在讓我們來看看JS屬于什么類型語言 解釋型語言 按編譯執行過程,可以分為編譯型語言和解釋型語言。比如 c 語言,必須先經過編譯生成目標文件,然后鏈接各個目標文件和庫...
閱讀 2080·2023-04-25 17:57
閱讀 1287·2021-11-24 09:39
閱讀 2487·2019-08-29 16:39
閱讀 3317·2019-08-29 13:44
閱讀 3126·2019-08-29 13:14
閱讀 2323·2019-08-26 11:36
閱讀 3815·2019-08-26 11:00
閱讀 951·2019-08-26 10:14