作者|Matthew MacDonald
譯者|王強
編輯|王文婧
誰能取代 JavaScript 似乎是一個老生常談的話題,很多人都提出過各自不同的看法。本文作者則提出了一個新的視角供你參考:JavaScript 風頭正勁,但 WebAssembly 可能已經敲響了它的喪鐘。
有些程式設計語言很受歡迎,還有些語言隻是一種"必需品"而已。對于許多程式員來說,JavaScript 就屬于後者——每一位前端開發人員都需要了解這門語言,但人們用不着真心喜愛它。
十年前,我們還很難看出 JavaScript 将會統治世界。Java、Flash 和 Silverlight 等平台曾位于舞台中心。這三大技術都需要使用浏覽器插件來完成工作,它們也都用另一種使用者界面方法取代了 HTML。這種方法使它們在功能層面遙遙領先于 JavaScript——比如,早在video元素、CSS 動畫規範或 HTML 畫布誕生之前,我們就可以添加視訊、動畫和繪圖。但這種方法也讓它們走入了黃昏。當移動浏覽需求爆炸式增長,HTML 開始擁抱這一趨勢的時候,其他平台就成為了時代的眼淚。
這段諷刺的曆史如今要重演了。在 JavaScript 征服世界的同時,有人播下了一顆小小的種子,這顆種子可能在将來的某一天成長為參天大樹,敲響 JavaScript 的喪鐘——這就是名為 asm.js 的實驗性技術。
不過展開這個故事之前,我們先退後一步看一看現狀。
轉譯:目前方法
自從我們有了 JavaScript,開發人員就一直在設法繞開它。早期的一種方法是使用插件把代碼從浏覽器中剝離(結果失敗了)。另一個想法是開發出可以轉換代碼的開發工具,換句話說就是采用另一種更受人尊敬的語言編寫代碼,然後将其轉換為 JavaScript。這樣開發人員就可以獲得他們需要的全平台支援,同時并不會弄髒自己的雙手。
将一種語言轉換為另一種語言的過程稱為 轉譯(transpiling),其存在一些明顯的缺陷。進階語言有着各自不同的功能、文法和習慣表達,你不可能把一種語言中的每一行都映射到另一種語言中的等效構造上。就算你能做到這一點也會留下許多坑。如果社群停止開發你最喜歡的轉譯器該怎麼辦?如果轉譯器自己就引入了許多錯誤該怎麼辦?想要插入 Angular、React 或 Vue 這樣的 JavaScript 架構又要怎麼解決?如果你會的語言和同僚不一樣,你又該如何與團隊協作?
程式設計行業中很多情況本質都是一樣的,那就是一種工具的水準主要取決于它背後社群的繁榮程度。

如今轉譯器是很常見的,但它們的用途幾乎隻有一條——那就是處理向後相容性。
開發人員可能會編寫最前沿的 JavaScript,然後使用 Babel 這樣的轉譯器将其代碼轉換為等效(但不太優雅)的老式 JavaScript 代碼,以便在所有位置運作。或者更好的辦法是,他們使用 TypeScript(一種現代化的 JavaScript,添加了強類型、泛型和非空類型等功能),然後将其轉換為 JavaScript。但不管是哪種方法,你都逃不出 JavaScript 的手掌心。
Asm.js:墊腳石
全新可能性的第一縷曙光來自 asm.js,這是 Mozilla 的開發人員在 2013 年完成的一項古怪的實驗。當時他們正在尋找在浏覽器中運作高性能代碼的方法。但 asm.js 并沒有像插件那樣嘗試在浏覽器外部運作;相反,它的目标是直接通過 JavaScript 虛拟機打出一條通道。
從本質上講,asm.js 是簡潔且優化的 JavaScript 文法。它比普通的 JavaScript 運作得更快,因為它避免了這種語言中較慢的動态部分。而且支援它的 Web 浏覽器也可以應用其他優化,進而顯著提升性能。換句話說,asm.js 遵循黃金法則——不要破壞 Web——同時提供了一條未來改進的途徑。Firefox 團隊使用 asm.js 以及稱為 Emscripten 的轉譯工具把用 C++ 建構的實時 3D 遊戲放入 Web 浏覽器中,需要的條件僅僅是 JavaScript 和達成目标的雄心壯志。
運作在 asm.js 上的虛幻引擎
asm.js 的最大意義在于,它迫使開發人員重新思考 JavaScript 扮演的角色。Asm.js 代碼是 JavaScript,但這些代碼并不是讓程式員手工讀寫的。相反,asm.js 代碼是由自動化流程(轉譯器)建構,并直接提供給浏覽器的。JavaScript 是媒介,但不是資訊本身。
WebAssembly:一項新技術
盡管 asm.js 實驗做出了一些令人眼花缭亂的示範,但主流開發人員大都無動于衷。對他們來說,這隻是又一項有趣的技術概念而已。但随着 WebAssembly 的誕生,情況發生了變化。
WebAssembly 既是 asm.js 的後繼産品,又是一項截然不同的技術。這是一種緊湊的二進制代碼格式。像 asm.js 一樣,WebAssembly 代碼也被輸入到 JavaScript 執行環境中。它具有相同的沙箱和相同的運作時環境。與 asm.js 一樣,WebAssembly 的轉譯機制也可以進一步提升效率。但是現在這種潛力比以前大得多,并且浏覽器可以完全跳過 JavaScript 解析階段。對于一段普通的邏輯(例如一段很費時的計算)來說,WebAssembly 的執行速度遠遠快于正常的 JavaScript,幾乎與原生編譯的代碼一樣快。
WebAssembly 處理流水線的簡化視圖
想知道 WASM 長什麼樣的話,可以想象你有一個 C 函數,如下所示:
int factorial(int n) {
if (n == 0)
return 1;
else
return n * factorial(n-1);
}
它編譯成 WASM 代碼後就成了下面這個樣子:
get_local 0
i64.eqz
if (result i64)
i64.const 1
else
get_local 0
get_local 0
i64.const 1
i64.sub
call 0
i64.mul
end
開始向網絡中傳送時,WASM 代碼會進一步壓縮為二進制編碼。
WebAssembly 設計為編譯器的目标。你永遠用不着親自動手寫它的代碼。(但如果你想深入探索一番,自己寫也是可以的。)
WebAssembly 誕生于 2015 年。今天,桌面和移動裝置上的四大浏覽器(Chrome、Edge、Safari 和 Firefox)都完全支援它。Internet Explorer 是不支援的,盡管可以将 WebAssembly 代碼轉換為 asm.js 來實作向後相容。(相容性的代價是性能損失。請讓 IE 走進曆史吧!
WebAssembly 與 Web 開發的未來
WebAssembly 是開箱即用的,為開發人員提供了一種(通常使用 C++)編寫優化代碼邏輯的途徑。這是強大的能力,但應用範圍相對較窄。當你需要改善複雜計算的性能時這種方法很有用(例如,fastq.bio 使用 WebAssembly 加快了他們的 DNA 測序計算。。如果你要移植高性能遊戲或編寫在浏覽器中運作的模拟器,這種能力也很重要。但如果這就是 WebAssembly 的全部實力,那其實也沒什麼可激動的——光是這點東西可沒希望取代 JavaScript。但是 WebAssembly 還為架構開發人員提供了一條狹窄的路徑,使他們可以将其平台塞入 JavaScript 環境中。
這下事情就變得有趣了。WebAssembly 無法繞開 JavaScript,因為它已鎖定在 JavaScript 運作時環境中了。實際上,WebAssembly 需要與最起碼 少量 的普通 JavaScript 代碼搭配運作,因為前者無法直接通路網頁。這意味着如果不經過 JavaScript 層,WASM 就無法操縱 DOM 或接收事件。
聽起來這個限制是緻命的。但是聰明的開發人員已經找到了通過 WebAssembly 塞進他們自己的運作時的辦法。例如,微軟的 Blazor 架構會下載下傳一個小型.NET 運作時作為已編譯的 WASM 檔案。這個運作時處理 JavaScript 互操作,并提供基本服務(如垃圾回收)和更進階别的功能(布局、路由和使用者界面小部件等)。換句話說,Blazor 使用了一個駐留在另一個虛拟機中的虛拟機,堪稱《盜夢空間》級别的悖論,也是一種在浏覽器中運作非 JavaScript 應用程式架構的巧妙方法。
Blazor 并不是唯一一個由 WebAssembly 支援的實驗。還可以看看 Pyodide,其旨在将 Python 放入浏覽器中,它帶有用于資料分析的進階數學工具包。
這就是未來。WebAssembly 最初是為了滿足 C++ 和 Rust 等需求而誕生的,卻很快就被用來開發目标更加遠大的實驗。不久的将來,它就會支援非 JavaScript 架構與 Angular、React 和 Vue 等基于 JavaScript 的對手同台競技。
而且 WebAssembly 仍在迅速發展。它目前的實作隻是一款最小可行産品——隻夠在一些重點場景中使用,還不是萬能的 Web 開發方法。随着 WebAssembly 的推廣,它也會不斷進化。如果像 Blazor 這樣的平台流行起來,WebAssembly 可能會增加對直接 DOM 通路的支援。浏覽器開發商還在計劃添加垃圾回收和多線程支援,這樣運作時就不需要自己實作這些細節。
看起來這條發展道路漫長而充滿變數,但請回想一下 JavaScript 的曆史。首先,我們發現 JavaScript 能做到的事情都會寫成 JS 代碼。然後我們意識到,如果一件事情重複的次數夠多,浏覽器就會讓它做得更好,如此循環。如果 WebAssembly 開始流行,它将進入一個良性循環,不斷發展,很容易就能超越 JavaScript 的固有優勢。
人們經常說,WebAssembly 并不是用來代替 JavaScript 的。但這句話對所有革命性平台都是一樣的。JavaScript 當初并不是要取代嵌入浏覽器的 Java。Web 應用程式并非旨在替代桌面應用。但一旦能做到這些,它們必然會走上那條路。
作者介紹
Matthew MacDonald 是教師、程式員和許多大部頭的作者。
原文連結:
https://medium.com/young-coder/what-replaces-javascript-a6493b4e2d6e