編譯型&解釋型、動態(tài)語言&靜態(tài)語言、強(qiáng)類型語言&弱類型語言

順著javascript在mdn上的定義,扒到了這么一篇文章:about JavaScript.

It is a prototype-based, multi-paradigm scripting language that is dynamic, and supports object-oriented, imperative, and functional programming styles.

實(shí)際上一開始我就知道javascript是弱類型語言,動態(tài)類型語言,解釋型語言,但其實(shí)對這幾個(gè)概念并不清晰。今日梳理如下。

動態(tài)|靜態(tài)類型語言

有三個(gè)名詞容易混淆:
Dynamic Programming Language (動態(tài)語言或動態(tài)編程語言)
Dynamically Typed Language (動態(tài)類型語言)
Statically Typed Language (靜態(tài)類型語言)
對于第一個(gè)我還并不是很理解wiki的內(nèi)容。本文所指的動態(tài)靜態(tài)語言,主要指的是動態(tài)類型和靜態(tài)類型語言。
(1)動態(tài)類型語言:在運(yùn)行期間(run time)才去做數(shù)據(jù)類型檢查,也就是說,在用動態(tài)類型的語言編程時(shí),永遠(yuǎn)也不用給任何變量指定數(shù)據(jù)類型,該語言會在你第一次賦值給變量時(shí),在內(nèi)部將數(shù)據(jù)類型記錄下來。Python和Ruby就是一種典型的動態(tài)類型語言。
(2)靜態(tài)類型語言:在編譯期間(compile time)做數(shù)據(jù)類型檢查。也就是說在寫程序時(shí)要聲明所有變量的數(shù)據(jù)類型,C/C++是靜態(tài)類型語言的典型代表。

拋開語言的概念,單獨(dú)討論動靜態(tài)類型也很有意思。比如:Hashmap 就是動態(tài)類型 Map 就是靜態(tài)類型,因而編譯器可以將任何 map objects
視作某種類型的 Map——參考高票答案中class Foo案例

cf.:Compile:將用戶代碼轉(zhuǎn)換為機(jī)器代碼的過程。Build:生成可執(zhí)行文件,Build的過程包括了Compile的過程?!?/p>

強(qiáng)/弱類型語言(Strong_and_weak_typing)

強(qiáng)弱,動靜類型是兩個(gè)概念
比如:
Python是強(qiáng)類型 + 動態(tài)類型
JS是弱類型 + 動態(tài)類型

弱/強(qiáng)類型指的是語言類型系統(tǒng)的類型檢測的嚴(yán)格程度。強(qiáng)弱類型有很多定義,甚至定義與定義之間都是相互矛盾的,所以wiki上有這樣一句話:

it is possible to defend claims about most programming languages that they are either strongly or weakly typed.

但注意隱式類型轉(zhuǎn)換也可以發(fā)生在強(qiáng)類型語言中。比如:

class Untitled {
    public static void main(String[] args) {
        // 運(yùn)行之后可以正常在控制臺打印
        if("1"+1=="11"){System.out.println("=======");}
    }
}

實(shí)際上這是一種特殊的隱式形類型轉(zhuǎn)換。
也可以發(fā)生在 java 的 float int 等數(shù)字類型轉(zhuǎn)換中。
java中+的字符串連接操作符的特殊用法。只有在一個(gè)有字符串,一個(gè)是非字符串的時(shí)候才會發(fā)生。

靜態(tài)語言動態(tài)語言說的是類型檢測發(fā)生的階段。
動態(tài)/靜態(tài)類型,指的是聲明一個(gè)變量之后,它是否可以存儲(指向)不同類型的變量。靜態(tài)動態(tài)類型,是以類型檢測發(fā)生的階段不同進(jìn)行區(qū)分的兩個(gè)proposition互為因果。
比如:正是因?yàn)轭愋蜋z測發(fā)生在編譯(預(yù)編譯)階段(一般build automatically),所以java才不允許對變量變更類型,所以它是靜態(tài)類型語言。

編譯型和解釋性語言

用編譯型語言寫的程序執(zhí)行之前,需要一個(gè)專門的編譯過程,通過編譯系統(tǒng)(不僅僅只是通過編譯器,編譯器只是編譯系統(tǒng)的一部分)把高級語言翻譯成機(jī)器語言,把源高級程序編譯成為機(jī)器語言文件,比如windows下的exe文件。以后就可以直接運(yùn)行而不需要編譯了,因?yàn)榉g只做了一次,運(yùn)行時(shí)不需要翻譯,所以編譯型語言的程序執(zhí)行效率高,但也不能一概而論,部分解釋型語言的解釋器通過在運(yùn)行時(shí)動態(tài)優(yōu)化代碼,甚至能夠使解釋型語言的性能超過編譯型語言。
解釋則不同,解釋型語言編寫的程序不需要編譯。解釋型語言在運(yùn)行的時(shí)候才編譯。

舉個(gè)栗子。

作為編譯型語言,JAVA程序要被統(tǒng)一編譯成字節(jié)碼文件——文件后綴是class。此種文件在java中又稱為類文件。java類文件不能再計(jì)算機(jī)上直接執(zhí)行,它需要被java虛擬機(jī)翻譯成本地的機(jī)器碼后才能執(zhí)行,而java虛擬機(jī)的翻譯過程則是解釋性的。java字節(jié)碼文件首先被加載到計(jì)算機(jī)內(nèi)存中,然后讀出一條指令,翻譯一條指令,執(zhí)行一條指令,該過程被稱為java語言的解釋執(zhí)行,是由java虛擬機(jī)完成的。而在現(xiàn)實(shí)中,java開發(fā)工具JDK提供了兩個(gè)很重要的命令來完成上面的編譯和解釋(翻譯)過程。兩個(gè)命令分別是java.exe和javac.exe,前者加載java類文件,并逐步編譯為字節(jié)碼文件,而另一個(gè)命令則對應(yīng)了java語言的解釋(javac.exe)過程。在次序上,java語言是要先進(jìn)行編譯的過程,接著解釋執(zhí)行。

但隨著硬件的升級和設(shè)計(jì)思想的變革,編譯型和解釋型語言越來越籠統(tǒng),主要體現(xiàn)在一些新興的高級語言上,而解釋型語言的自身特點(diǎn)也使得編譯器廠商愿意花費(fèi)更多成本來優(yōu)化解釋器,解釋型語言性能超過編譯型語言也是必然的。

額外知識

任何語言都能實(shí)現(xiàn)另一個(gè)語言的解析器

參考文獻(xiàn)

解釋型語言和編譯型語言的區(qū)別
https://en.wikipedia.org/wiki/Strong_and_weak_typing
JS是動態(tài)弱類型語言的理解

延伸閱讀

boxing——類型包裹的概念

代碼在線運(yùn)行工具

https://codepad.remoteinterview.io/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容