1974年,兩位美國計算機科學家Liskov,Zilles提出強類型語言的概念。java
在強類型語言中,當一個對象從調用函數傳遞到被調用函數時,其類型必須與被調用函數中聲明的類型兼容c++
function A(){
B(x)
}
function B(y){
// y能夠被賦值x,程序運行良好
}
複製代碼
這是一個較爲寬泛的定義,並無闡述具體的規則,後人對強類型語言的定義則會更精確一些。瀏覽器
強類型語言:不容許改變變量的數據類型,除非進行強制類型轉換。bash
以java爲例函數
public class HelloWorld {
public static void main(String []args) {
int x =1;
boolean y = true;
x = y;
System.out.println(x);
}
}
複製代碼
定義x爲數字,y爲布爾值,將y賦值給x,會報錯。工具
public class HelloWorld {
public static void main(String []args) {
int x =1;
char y = 'a'
x = y;
System.out.println(x); // 97
}
}
複製代碼
定義x爲數字,y爲字符,將y賦值給x,最終值爲97,Java在這裏進行了強制類型轉換,將字符a的ASCll碼賦值給了x,這樣x的數據類型依舊是整型。性能
弱類型語言:變量能夠被賦予不一樣的值單元測試
仍然是剛纔的例子,在瀏覽器中用js來運行。測試
能夠看到,x的類型變成了它被賦值的那個變量的類型。總而言之,強類型語言對變量的類型的轉換有嚴格的限制,除非進行強制類型轉換,不一樣類型的變量是不能相互賦值的,這樣就能夠避免一些低級錯誤。而弱類型語言就沒有什麼約束,能夠很靈活地進行類型轉換,但也更容易產生bug。ui
靜態類型語言:在編譯階段肯定全部變量的類型。
動態類型語言:在執行階段肯定全部變量的類型。
用一個例子來講明:
class C {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
function add(a) {
return a.x + a.y;
}
var c1 = new C(10, 20);
var c2 = new C('hello', 'world');
console.log(add(c1)); // 30
console.log(add(c2)); // helloworld
複製代碼
定義一個類C,併爲它添加了兩個屬性x和y,而後定義了一個add函數,用來把一個實例的全部屬性相加。當JS編譯器看到這段代碼時,它徹底不知道add函數裏的參數a的類型是什麼,只有執行的時候才知道。最終c1是數字相加,c2是字符串拼接。
一樣的代碼,用c++實現
class C {
public;
int x;
int y;
}
int add(C a) {
return a.x + a.y;
}
複製代碼
在編譯的時候,就知道C裏面的屬性x和y的類型是整型了。
從內存分配的角度來看上面的例子,c++因爲一開始就定義好了屬性類型是整型,因此假設x是基地址,那麼y就在基地址+4的位置上。js則不一樣,因爲一開始不知道屬性類型,因此也不知道每一個屬性要佔多少地址空間,因此須要額外的空間存儲屬性名,在程序運行時,再動態計算屬性的地址偏移量。
由此看來,動態類型語言在空間佔用上會有一些損耗。
總結一下二者的區別
靜態類型語言 | 動態類型語言 |
---|---|
對類型檢查嚴格 | 對類型檢查寬鬆 |
當即發現錯誤 | BUG不易被發現 |
運行性能較好 | 運行性能較差 |
自文檔化 | 可讀性較差 |
但動態類型語言也有方法來補救這些缺點,好比,
因此雖然js是一門動態弱類型語言,但它倒是目前最流行的語言之一,就是由於它的靈活和應用場景普遍。
最後,看一下各類語言的強弱類型和動態靜態類型吧。