特別說明,為便于查閱,文章轉自https://github.com/getify/You-Dont-Know-JS
在你一頭扎進這本書之前,你應當可以熟練地使用(在本書寫作時)最近版本的JavaScript,也就是通常所說的 ES5(技術上講是ES 5.1)。這里,我們打算好好談談即將到來的 ES6,同時放眼未來去看看JS將會如何繼續進化。
如果你還在JavaScript上尋找信心,我強烈推薦你首先讀一讀本系列的其他書目:
- 入門與進階:你是編程和JS的新手嗎?這就是你在開啟學習的旅程前需要查看的路線圖。
- 作用域與閉包:你知道JS的詞法作用域是基于編譯器(不是解釋器!)語義的嗎?你能解釋閉包是如何成為詞法作用域和函數作為值的直接結果的嗎?
-
this與對象原型:你能復述
this
綁定的四個簡單規則嗎?你有沒有曾經在JS中對付著去山寨“類”,而不是采取更簡單的“行為委托”設計模式?你聽說過 鏈接到其他對象的對象 (OOLO)嗎? - 類型與文法:你知道JS中的內建類型嗎?更重要的是,你知道如何在類型之間正確且安全地使用強制轉換嗎?你對JS文法/語法的微妙之處感到有多習慣?
- 異步與性能:你還在使用回調管理你的異步處理嗎?你能解釋promise是為什么/如何解決了“回調地獄”的嗎?你知道如何使用generator來改進異步代碼的易讀性嗎?到底是什么構成了JS程序和獨立操作的成熟優化?
如果你已經讀過了這些書目而且對它們涵蓋的內容感到十分輕松,那么現在是時候讓我們深入JS的進化過程來探索所有即將到來的以及未來會發生的改變了。
與ES5不同,ES6不僅僅是向語言添加的一組不算太多的新API。它包含大量的新的語法形式,其中的一些你可能會花上相當一段時間才能適應。還有幾種新的組織形式和為各種數據類型添加的新API。
對這門語言來說ES6十分激進。就算你認為你懂得ES5的JS,ES6也滿是 你還不懂的 新東西,所以做好準備!這本書探索所有你需要迅速掌握的ES6主要主題,并且窺見一下那些你應當注意的正在步入正軌的未來特性。
警告: 這本書中的所有代碼都假定運行在ES6+的環境中。在寫作本書時,瀏覽器和JS環境(比如Node.js)對ES6的支持相當不同,因此你的感覺可能將會不同。
版本
JavaScript標準在官方上被稱為“ECMAScript”(縮寫為“ES”),而且直到最近才剛剛完全采用順序數字來標記版本(例如,“5”代表“第五版”)。
最早的版本,ES1和ES2,并不廣為人知也沒有大范圍地被實現。ES3是JavaScript第一次廣泛傳播的基準線,并且構成了像IE6-8和更早的Android 2.x移動瀏覽器的JavaScript標準。由于一些超出我們討論范圍的政治原因,命運多舛的ES4從未問世。
在2009年,ES5正式定稿(在2011年出現了ES5.1),它在瀏覽器的現代革新和爆發性增長(比如Firefox,Chrome,Opera,Safari,和其他許多)中廣泛傳播,并作為JS標準穩定下來。
預計下一個版本的JS(從2013年到2014年和之后的2015年中的內容),在人們的討論中顯然地經常被稱為ES6。
然而,在ES6規范的晚些時候,有建議提及未來的版本號也許會切換到編年制,比如用ES2016(也叫ES7)來指代在2016年末之前被定稿的任何版本。有些人對此持否定意見,但是相對于后來的ES2015來說,ES6將很可能繼續維持它占統治地位的影響力。可是,ES2016事實上可能標志了新的編年制。
還可以看到,JS進化的頻度即使與一年一度的定版相比都要快得多。只要一個想法開始標準化討論的進程,瀏覽器就開始為這種特性建造原型,而且早期的采用者就開始在代碼中進行實驗。
通常在一個特性被蓋上官方承認的印章以前,由于這些早期的引擎/工具的原型它實際上已經被標準化了。所以也可以認為未來的JS版本將是一個特性一個特性的更新,而非一組主要特性的隨意集合的更新(就像現在),也不是一年一年的更新(就像可能將變成的那樣)。
簡而言之,版本號不再那么重要了,JavaScript開始變得更像一個常青的,活的標準。應對它的最佳方法是,舉例來說,不再將你的代碼庫認為是“基于ES6”的,而是考慮它支持的一個個特性。
轉譯
由于特性的快速進化,給開發者們造成了一個糟糕的問題,他們強烈地渴望立即使用新特性,而同時被被現實打臉 —— 他們的網站/app需要支持那些不支持這些特性的老版本瀏覽器。
在整個行業中ES5的方式似乎已經無力回天了,它典型的思維模式是,代碼庫等待幾乎所有的前ES5環境從它們的支持譜系中除名之后才開始采用ES5。結果呢,許多人最近(在本書寫作時)才開始采用strict
模式這樣的東西,而它早在五年前就在ES5中定稿了。
對于JS生態系統的未來來說,等待和落后于語言規范那么多年被廣泛地認為是一種有害的方式。所有負責推動語言演進的人都渴望這樣的事情;只要新的特性和模式以規范的形式穩定下來,并且瀏覽器有機會實現它們,開發者就開始基于這些新的特性和模式進行編碼。
那么我們如何解決這個看起來似乎矛盾的問題?答案是工具,特別是一種稱為 轉譯(transpiling) 的技術(轉換+編譯)。大致上,它的想法是使用一種特殊的工具將你的ES6代碼轉換為可以在ES5環境中工作的等價物(或近似物!)。
例如,考慮屬性定義縮寫(見第二章的“對象字面擴展”)。這是ES6的形式:
var foo = [1,2,3];
var obj = {
foo // 意思是 `foo: foo`
};
obj.foo; // [1,2,3]
這(大致)是它如何被轉譯:
var foo = [1,2,3];
var obj = {
foo: foo
};
obj.foo; // [1,2,3]
這是一個微小但令人高興的轉換,它讓我們在一個對象字面聲明中將foo: foo
縮寫為foo
,如果名稱相同的話。
轉譯器為你實施這些變形,這個過程通常是構建工作流的一個步驟 —— 與你進行linting,壓縮,和其他類似操作相似。
填補(Shims/Polyfills)
不是所有的ES6新特性都需要轉譯器。填補(也叫shims)是一種模式,在可能的情況下,它為一個新環境的行為定義一個可以在舊環境中運行的等價行為。語法是不能填補的,但是API經常是可以的。
例如,Object.is(..)
是一個用來檢查兩個值嚴格等價性的新工具,它不帶有===
對于NaN
和-0
值的那種微妙的例外。Object.is(..)
的填補相當簡單:
if (!Object.is) {
Object.is = function(v1, v2) {
// 測試 `-0`
if (v1 === 0 && v2 === 0) {
return 1 / v1 === 1 / v2;
}
// 測試 `NaN`
if (v1 !== v1) {
return v2 !== v2;
}
// 其他的一切情況
return v1 === v2;
};
}
提示:注意外部的if
語句守護性地包圍著填補的內容。這是一個重要的細節,它意味著這個代碼段僅僅是為這個API還未定義的老環境而定義的后備行為;你想要覆蓋既存API的情況是非常少見的。
有一個被稱為“ES6 Shim”( https://github.com/paulmillr/es6-shim/ )的了不起的ES6填補集合,你絕對應該將它采納為任何新JS項目的標準組成部分!
看起來JS將會繼續一往無前的進化下去,同時瀏覽器也會持續地小步迭代以支持新特性,而不是大塊大塊地更新。所以跟上時代的最佳策略就是在你的代碼庫中引入填補,并在你的構建流程中引入一個轉譯器步驟,現在就開始習慣新的現實。
如果你決定維持現狀,等待不支持新特性的所有瀏覽器都消失才開始使用新特性,那么你將總是落后于時代。你將可悲地錯過所有新發明的設計 —— 而它們使編寫JavaScript更有效,更高效,而且更健壯。
復習
ES6(有些人可能會稱它為ES2015)在本書寫作時剛剛定稿,它包含許多你需要學習的新東西!
但更重要的是,它將你的思維模式與JavaScript新的進化方式相接軌。不是僅僅為了等待某些官方文檔投票通過而耗上許多年,就像以前許多人做的那樣。
現在,JavaScript特性一準備好就會在瀏覽器中實現,由你來決定是否現在就搭上早班車,還是去玩兒代價不菲的追車游戲。
不管未來的JavaScript采用什么樣的標簽,它都將會以比以前快得多的速度前進。為了使你位于在這門語言前進方向上的最前列,轉譯和填補是不可或缺的工具。
如果說對于JavaScript的新現實有什么重要的事情需要理解,那就是所有的JS開發者都被強烈地懇求從落后的一端移動到領先的一段。而學習ES6就是這一切的開端!