類型系統java
類型安全 —— 強類型 VS. 弱類型python
類型檢查 —— 靜態類型 VS. 動態類型編程
爲何JS是弱類型且動態類型呢?安全
關於查資料對於編譯型語言和解釋型語言的知識點補充編程語言
這篇文章要先討論一些概念,這些概念咱們在開始學習JavaScript的時候就知道了,JavaScript是一個弱類型且動態類型的語言
,那麼這些概念具體這裏作了整理。以後還要重點討論的是 JavaScript自有類型系統的問題
,以及如何藉助一些優秀的技術方案,解決這些問題。函數
咱們常常用兩個維度去描述一個編程語言的特性,這兩個維度不要混淆,強類型並非動態類型...工具
強類型 :要求語言層面限制函數的實參類型必須與形參類型相同。弱類型 : 語言層面不會限制實參的類型。學習
下面舉個例子:開發工具
// Java class Main { // 這裏定義了傳入的參數是int類型,那麼實際的時候也應該是int類型 static void foo(int num) { System.out.printIn(num); } public static void main(Sting[] args) { // 下面的若是int類型就經過,若是不是int類型就會報錯 Main.foo(100); // ok Main.foo('100'); // error "100" is a string Main.foo(Integer.parseInt("100")); // ok } } // --------------------------------------------------- // JavaScript // 傳的時候沒有規定是什麼類型,那麼實參是什麼類型都不會報錯 function foo(num) { console.log(num) } foo(100) // ok foo('100') // ok foo(parseInt('100')) // ok
因爲這種強弱類型之分根本不是某一個權威機構的定義,因此以後的人們對制定的細節出現了不同的理解。大體也就是說強類型有更強的類型約束,而弱類型中幾乎沒有什麼約束。
強類型語言中不容許有任何的隱式類型轉換,而弱類型語言則容許任意的數據隱式類型轉換。
測試
// JavaScript // js報的錯誤都是在代碼層面,運行的時候經過邏輯判斷手動拋出的,並非語法層面的類型限制 // 下面'100'是字符串,在作減法的時候進行了隱式類型轉換,轉換成了Number類型,最後獲得的結果是50,Number類型。 > '100' - 50 50 // 下面字符串進行隱式類型轉換,不是數字的成爲NaN(不是數字) > Math.floor('foo') NaN // 布爾值進行隱式類型轉換,轉成了數字1 > Math.floor(true) 1
# python # 這裏沒法進行隱式類型轉換,會在語法層面上報類型錯誤 > '100' - 50 TypeError: unsupported operand type(s) for -: 'str' and 'int' > abs('foo') TypeError: bad operand type for abs(): 'str'
都比較統一,沒什麼爭議
靜態類型 :一個變量聲明時它的類型就是明確的,聲明事後,類型不能修改。動態類型 :運行階段才能夠明確變量的類型,並且變量的類型隨時能夠改變。因此動態類型語言中的變量沒有類型,變量中存放的值時有類型的。
// Java class Main { public static void main(String[] args) { // 一開始就定了num的類型是int,若是修改也只能修改爲int類型,若是修改爲string就會報錯 int num = 100; num = 50; // ok num = '100' // error System.out.printInt(num); } } // JavaScript // 能夠隨意修改num的類型 var num = 100 num = 50 // ok num = '100' // ok num = true // ok console.log(num)
靜態類型不能修改變量的類型,動態類型能夠隨時去修改變量的類型。
JavaScript是弱類型且動態類型的語言,靈活多變,能夠進行 隱式轉換 ,也能夠進行 類型推斷 ,可是缺失了類型系統的可靠性。
JavaScript
應用簡單,因此並無複雜的類型系統JavaScript
是腳本語言,沒有編譯環節,因此設計成靜態語言是沒有意義的JavaScript
應用愈來愈複雜,開發週期也愈來愈長,愈來愈大的項目幾百行代碼已經不知足現狀了,因此如今弱類型已經成爲了JavaScript
的短板。const obj = {} obj.foo() // TypeError: obj.foo is not a function // 下面這個延時器,在時間到了以後纔會運行,給測試帶來麻煩 setTimeout(() => { obj.foo() }, 100000)
// 不明確是數字,因此結果不同 function sum (a, b) { return a + b } console.log(sum(100, 100)) // 200 console.log(sum(100, '100')) // 100100
// 定義一個字符串,對象的屬性名不能是對象,會自動轉換成字符串,若是不知足就會有問題 const obj = {} obj[true] = 100 obj[{name:1}] = 1 console.log(obj) // {true: 100, [object Object]: 1} console.log(obj['true']) // 100 console.log(obj["[object Object]"]) // 1
function sum (a, b) { if (typeof a !== 'number' || typeof b !== 'number') { throw new TypeError('arguments must be a number') } return a + b }
這裏以後會進行內容補充
使用專門的編譯器,針對特定的平臺,將高級語言源代碼一次性的編譯成可被該平臺硬件執行的機器碼,幷包裝成該平臺所能識別的可執行性程序的格式。
編譯型語言一次性的編譯成平臺相關的機器語言
文件,運行時脫離開發環境,與特定平臺相關,通常沒法移植到其餘平臺,現有的C、C++、Objective等都屬於編譯型語言。
使用專門的解釋器對源程序逐行解釋成特定平臺的機器碼並當即執行。是代碼在執行時才被解釋器一行行動態翻譯成機器語言和執行
,而不是在執行以前就完成翻譯。解釋型語言每次運行都須要將源代碼解釋稱機器碼並執行,只要平臺提供相應的解釋器,就能夠運行源代碼,Python、Java、
JavaScript
等屬於解釋型語言。