順著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)弱類型語言的理解