JavaScript類型系統

目錄

  • 類型系統java

    • 類型安全 —— 強類型 VS. 弱類型python

      • 二者之間的區別
    • 類型檢查 —— 靜態類型 VS. 動態類型編程

      • 二者之間的區別
  • JavaScript類型系統的特徵
  • 爲何JS是弱類型且動態類型呢?安全

    • 爲何須要類型檢查呢?
    • 弱類型的不足
    • 強類型的優點
  • JavaScript自有類型系統問題的解決方案
  • 關於查資料對於編譯型語言和解釋型語言的知識點補充編程語言

    • 編譯型語言
    • 解釋型語言

這篇文章要先討論一些概念,這些概念咱們在開始學習JavaScript的時候就知道了,JavaScript是一個弱類型且動態類型的語言,那麼這些概念具體這裏作了整理。以後還要重點討論的是 JavaScript自有類型系統的問題,以及如何藉助一些優秀的技術方案,解決這些問題。函數

類型系統

咱們常常用兩個維度去描述一個編程語言的特性,這兩個維度不要混淆,強類型並非動態類型...工具

  • 強類型與弱類型,這是從類型安全的維度分類
  • 靜態類型與動態類型,這是從類型檢查的維度分類

類型安全 —— 強類型 VS. 弱類型

強類型 :要求語言層面限制函數的實參類型必須與形參類型相同。

弱類型 : 語言層面不會限制實參的類型。學習

下面舉個例子:開發工具

// 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'

類型檢查 —— 靜態類型 VS. 動態類型

都比較統一,沒什麼爭議

靜態類型 :一個變量聲明時它的類型就是明確的,聲明事後,類型不能修改。

動態類型 :運行階段才能夠明確變量的類型,並且變量的類型隨時能夠改變。因此動態類型語言中的變量沒有類型,變量中存放的值時有類型的。

// 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是弱類型且動態類型的語言,靈活多變,能夠進行 隱式轉換 ,也能夠進行 類型推斷 ,可是缺失了類型系統的可靠性。

爲何JS是弱類型且動態類型呢?

  • 早前的JavaScript應用簡單,因此並無複雜的類型系統
  • JavaScript是腳本語言,沒有編譯環節,因此設計成靜態語言是沒有意義的

爲何須要類型檢查呢?

  • 由於如今的JavaScript應用愈來愈複雜,開發週期也愈來愈長,愈來愈大的項目幾百行代碼已經不知足現狀了,因此如今弱類型已經成爲了JavaScript的短板。
  • 這些東西只能經過約定去規避問題,可是在大型項目中經過人爲約定存在隱患。

弱類型的不足

  1. 只有在運行階段才能發現代碼的異常,代碼沒有執行的時候也沒法發現代碼異常,在隱藏比較深的狀況下,測試不能百分百覆蓋。
const obj = {}
obj.foo()  // TypeError: obj.foo is not a function

// 下面這個延時器,在時間到了以後纔會運行,給測試帶來麻煩
setTimeout(() => {
    obj.foo()
}, 100000)
  1. 函數參數類型不肯定,輸入的結果有誤差
// 不明確是數字,因此結果不同
function sum (a, b) {
    return a + b
}

console.log(sum(100, 100)) // 200
console.log(sum(100, '100')) // 100100
  1. 隱式類型轉換在對象屬性名轉化成字符串,裏面的內容會有不少的問題
// 定義一個字符串,對象的屬性名不能是對象,會自動轉換成字符串,若是不知足就會有問題
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

強類型的優點

  1. 錯誤在開發階段就會暴露,越早發現越好
  2. 代碼更智能,編碼更準確(開發工具的智能提示由於有變量類型纔有提示)
  3. 重構更牢靠(若是項目中不少地方用到的成員,須要刪除成員或者修改爲員名稱的時候,弱類型語言會有隱患)
  4. 減小沒必要要的類型判斷
function sum (a, b) {
    if (typeof a !== 'number' || typeof b !== 'number') {
        throw new TypeError('arguments must be a number')
    }
    return a + b
}

JavaScript自由類型系統問題的解決方案

這裏以後會進行內容補充

  • flow —— JavaScript靜態類型檢查器
  • TypeScript —— JavaScript超集

關於查資料對於編譯型語言和解釋型語言的知識點補充

編譯型語言

使用專門的編譯器,針對特定的平臺,將高級語言源代碼一次性的編譯成可被該平臺硬件執行的機器碼,幷包裝成該平臺所能識別的可執行性程序的格式。

編譯型語言一次性的編譯成平臺相關的機器語言 文件,運行時脫離開發環境,與特定平臺相關,通常沒法移植到其餘平臺,現有的C、C++、Objective等都屬於編譯型語言。

解釋型語言

使用專門的解釋器對源程序逐行解釋成特定平臺的機器碼並當即執行。是 代碼在執行時才被解釋器一行行動態翻譯成機器語言和執行,而不是在執行以前就完成翻譯。

解釋型語言每次運行都須要將源代碼解釋稱機器碼並執行,只要平臺提供相應的解釋器,就能夠運行源代碼,Python、Java、JavaScript等屬於解釋型語言。

相關文章
相關標籤/搜索