ReasonML——新的前端強類型語言簡介

背景介紹

從有前端到如今,JavaScript 語言一直都是實現前端邏輯的首選。可是,因爲 JavaScript 是一個弱類型語言,很難進行相關的類型檢測。所以在構建大型應用時,使用 JavaScript 不免會遇到一些隱式類型轉換等相關的問題,從而致使程序的 bug。javascript

在當前的選擇中,有兩個流派,都可以解決 JavaScript 弱類型語言帶來的弊病,給前端帶來強類型語言的支持。前端

  • 第一個是 Facebook 提出的 Flow——這個的優勢在於咱們可以在不對現有代碼進行任何改造的狀況下,爲現有的代碼增長一個靜態類型檢測器,從而避免因爲類型轉換等問題帶來的 bug。
  • 第二個是以微軟開發的 TypeScript 爲首的前端新強類型語言——這類語言的優點是從根本上支持了強類型語言,能夠在編譯時經過類型推導與判斷來從根本上解決類型轉換問題,約束開發模型。可是,這類語言的缺點也很是明顯,若是須要支持相關的類型檢測和推導,那麼就須要對原有的代碼進行改造,一定會花費必定的人力。在強類型語言中,也分爲了兩種類型。
    • 第一種是 TypeScript 這類對 JavaScript 兼容的語言——正如前面所說,TypeScript 的優點在於:它可以徹底兼容 JavaScript 語言。具體是什麼意思呢,就是說你的代碼能夠是部分 TypeScript 語言,部分 JavaScript 語言的。TypeScript 的代碼能夠調用 JavaScript 的代碼,同時反過來也能夠成立;缺點也是因爲對 JavaScript 的兼容:因爲須要徹底兼容 JavaScript,所以它沒有辦法捨棄一些 JavaScript 中的一些缺陷。
    • 第二種則是咱們在本文中須要介紹的 ReasonML ,這類對 JavaScript 不兼容的語言——與第一種徹底相反,因爲不須要兼容 JavaScript,咱們能夠徹底捨棄 JavaScript 的缺陷,用一套新的語法規則來實現咱們的需求;可是,因爲不兼容 JavaScript 語言,所以咱們在開發時只能從頭開始進行項目的開發,也不能充分發揮 JavaScript 生態帶來的優點。

做爲最近被你們關注的愈來愈多的強類型語言,ReasonML 的發展也是須要咱們持續關注的。java

ReasonML 起源

說了這麼多背景,咱們來正式介紹下 ReasonML 這門語言。首先,讓咱們來看下[官網][1]對於 ReasonML 的介紹。git

Reason lets you write simple, fast and quality type safe code while leveraging both the JavaScript & OCaml ecosystems. Reason利用 JavaScript 和 OCaml 語言的生態,讓你編寫簡單、快速和高質量類型安全的代碼。github

從這個介紹中咱們能夠知道, ReasonML 是從 OCaml 語言衍生出來的,能夠支持 JavaScript 的新的強類型語言。首頁介紹中,還提到了這個語言的三個特色:npm

  • 無爭論的類型系統(Types without hassle),有效、安全的類型推論意味着你不多須要進行類型註釋,可是它能夠幫你檢查全部內容的類型。
  • 簡單的 JavaScript 交互(Easy JavaScript interop),能夠沒有任何麻煩的使用 NPM/Yarn 中的包,或者在你學習的時候,你甚至可使用一小段 JavaScript。
  • 靈活有趣(Flexible & Fun),適用於網站、動畫、遊戲、服務、腳手架工具等。經過這些例子咱們就能夠獲得靈感。

ReasonML 入門介紹

聽了這麼多關於 ReasonML 的介紹,咱們來簡單的看下相關的語法。經過相關的語法和示例,咱們可以幫助咱們更好的理解這門語言。json

咱們就使用官方的一些簡單的示例來快速入門這個語言。數組

安裝與編譯

由於目前瀏覽器沒法直接識別強類型語言,所以咱們須要經過編譯器,將強類型語言編譯成 JavaScript 之後纔可以在前端瀏覽器或者 Node.js 中運行。瀏覽器

首先,咱們來看下如何進行安裝:安全

npm install -g bs-platform
複製代碼

首先,咱們經過 NPM 來對編譯平臺 bs-platform 進行全局安裝,安裝完成後,咱們就可使用這個 cli 自帶的命令了。

安裝完成後,咱們須要初始化一個項目,所以咱們須要執行如下命令:

bsb -init my-new-project -theme basic-reason
複製代碼

經過這個命令,咱們就建立了一個名字爲 my-new-project 的項目文件了。

這個時候,咱們進入這個項目文件夾中,看看這裏面到底初始化了哪些東西。首先咱們來看下 package.json 文件。

{
  "name": "my-new-project",
  "version": "0.1.0",
  "scripts": {
    "build": "bsb -make-world",
    "start": "bsb -make-world -w",
    "clean": "bsb -clean-world"
  },
  "keywords": [
    "BuckleScript"
  ],
  "author": "",
  "license": "MIT",
  "devDependencies": {
    "bs-platform": "^4.0.18"
  }
}
複製代碼

接下來,咱們先來看下 src/Demo.re 文件的內容。

Js.log("Hello, BuckleScript and Reason!");
複製代碼

咱們須要重點關注的就是,咱們能夠經過 npm run build 命令來編譯整個項目,它會將 src/Demo.re 編譯成 src/Demo.re.js 文件。讓咱們來看下編譯出來的內容是什麼樣子的。

// Generated by BUCKLESCRIPT VERSION 4.0.18, PLEASE EDIT WITH CARE
'use strict';


console.log("Hello, BuckleScript and Reason!");

/* Not a pure module */
複製代碼

你們能夠看到,咱們經過 ReasonML 的編譯器,將 ReasonML 的代碼編譯成了 JavaScript。

語法介紹

說完了構建編譯相關的流程,咱們來正式看下 ReasonML 這門語言的語法。

ReasonML 的類型系統能夠自動進行類型推斷,在本文介紹中我會盡量詳細的進行介紹,可是若是沒有聲明具體類型,你們能夠自主進行推斷。

咱們能夠經過下面這個表格來快速看下當前的數據結構:

數據類型 示例
字符串 "Hello"
字符 'x'
整型數字 23, -23
浮點型數字 23.0, -23.0
整型數字加法 23 + 1
浮點型數字加法 23.0 +. 1.0
整型數字除法/乘法 2 / 23 * 1
浮點型數字除法/乘法 2.0 /. 23.0 *. 1.0
浮點型數字求冪 2.0 ** 2.0
字符串組合 "Hello " ++ "World"
比較運算符 >, <, >=, =<
布爾運算符 !, &&, ||
引用(淺)比較,結構(深)比較 ===, ==
不可變列表 [1, 2, 3]
不可變前置聲明(Immutable Prepend) [item1, item2, ...theRest]
元組(Tuple) [1, "string"]
數組 [|1, 2, 3|]
記錄(Records) type player = {score: int}; {score: 100}
對象 type tesla = {var red = "red"; pub color = red;}; tesla#color
註釋 /* Comment here */

這裏面有一些內容須要詳細介紹下差異。

  • 字符與字符串。在 ReasonML 中,字符與字符串分別是用單引號和雙引號來進行表示,而不是統一認爲是字符串,單雙引號通用。

  • 淺比較和深比較。在 JavaScript 中,===== 對於對象和數組之類的變量來講,都是進行地址的比較。而在 ReasonML 中,咱們能夠在運算符中實現深比較。

  • 不可變列表與數組。在 JavaScript 中,數組能夠存儲任意類型的內容。而在 ReasonML 中,出現了一個不可變列表,只能存儲同一種數據類型(好比所有都是整型數字),而且是不可變數據類型。ReasonML 的數組是一個可變數據類型,可是仍然只能存儲同一種數據類型。若是須要實現存儲不一樣的數據類型,則須要使用元組(Tuple)——一個不可變的有序類型,具體代碼以下:

    let ageAndName = (24, "Lil' Reason");
    複製代碼
  • 對象與記錄。在 ReasonML 中,出現了對象和記錄兩種類似的數據類型,咱們來看下二者的區別。記錄是一個須要提早聲明的默認不可變的數據結構,在 ReasonML 中推薦使用。而在 ReasonML 的對象,則是一個不須要提早聲明的數據結構。不過在 ReasonML 中,推薦優先使用記錄。

關於語法相關的內容,我只是簡單介紹了一下核心的數據結構,有不少內容沒有介紹到,若是你們想要系統的學習 ReasonML 的話,能夠看一下官方文檔

與 JavaScript 兼容方式

若是咱們須要在 ReasonML 中使用 JavaScript 代碼,咱們能夠按照以下的方法:

[%bs.raw {| console.log('here is some javascript for you') |}];
複製代碼

上面的代碼通過編譯後,能夠獲得以下的 JavaScript 代碼。

'use strict';
console.log('here is some javascript for you');
複製代碼

這個方法與全局注入變量的方式相似,會直接將上述代碼替換成編譯後的 JavaScript 代碼。所以咱們能夠這麼用:

let x = [%bs.raw {| 'here is a string from javascript' |}];
複製代碼

獲得的代碼爲:

var x = ( 'here is a string from javascript' );
複製代碼

與 JavaScript 語法差別

許多的語法差別咱們在上述語法介紹中都已經介紹過了,若是須要詳細的比對,能夠看官方文檔中的語法比較

總結

ReasonML 是一門比 TypeScript 約束嚴格的多的強類型語言(TypeScript 編譯報錯能夠選擇忽略掉,不影響使用)。強類型語言對於大型的項目開發來講,確實能夠帶來明顯的優點。可是,咱們能不可以大規模使用 ReasonML 呢?

先說下我的的基本判斷:持續關注,不建議在大型應用場景中使用。

從 ReasonML 目前的狀況來看,它與 TypeScript 很是類似。

TypeScript 因爲對 JavaScript 的生態徹底兼容,因此即便咱們須要進行部分代碼的重寫,咱們仍然能夠快速的複用 JavaScript 的強大生態。

而因爲 ReasonML 來講,這個方面就會明顯相差很多。與此同時,ReasonML 的相關語法與 JavaScript 相差較大,所以對於前端工程師的學習成原本說,也有必定的提提高。

綜上所述,若是你們須要在前端使用強類型語言來構建大型項目,建議選擇 TypeScript 語言。

若是在遷移 TypeScript 中有什麼問題,能夠看下我以前寫的一篇文章——舊項目 TypeScript 改造問題與解決方案記

做者介紹與轉載聲明

黃珏,2015年畢業於華中科技大學,目前任職於美團基礎研發平臺大象業務部,獨立負責大象 Web SDK 的開發與維護。

本文未經做者容許,禁止轉載。

相關文章
相關標籤/搜索