本文摘自《深刻理解JavaScript特性》,本書將JavaScript新特性融入簡單易懂的示例中,包括ES6及後續更新,助你大幅提高代碼表達能力。javascript
JavaScript之父Brendan Eich做序推薦。java
JavaScript 已經從 1995 年的一個爲了贏得戰略優點的市場營銷策略,變成了現在(2017 年)世界上使用最普遍的應用運行平臺中的核心編程語言。該語言再也不只是在瀏覽器中運行,如今也用於建立桌面和移動應用,還用於硬件設備,甚至是 NASA 的太空服設計。node
JavaScript 是如何作到這一步的,接下來它又會怎麼作呢?git
1995 年,NetScape 公司想要構建一個動態的網頁,但 HTML 沒法實現這一點。爲此,他們僱用 Brendan Eich 專門爲瀏覽器開發一門功能相似於 Scheme 的語言。Brendan 加入以後,得知上級主管但願這門語言的語法像 Java,並且這一決定已經開始實施。es6
Brendan 花 10 天寫出了 JavaScript 的第一個原型,主要實現了 Scheme 的一類函數和 Self 的原型等構造。這個初始版 JavaScript 的代號爲 Mocha。它沒有數組,沒有對象字面量,任何錯誤都會給出警告。此外,它也沒有異常處理,這也是現在仍有不少操做返回 NaN
或 undefined
的緣由。Brendan 對 DOM0 級和 JavaScript 第一個版本的實現成爲了這門語言標準化的基礎。github
1995 年 9 月,Netscape Navigator 2.0 beta 版發佈,JavaScript 的修訂版也內置其中,對外宣傳時名叫 LiveScript。同年 12 月,Navigator 2.0 beta 3 發佈,此時 LiveScript 又從新命名爲 JavaScript(後成爲 Sun 的註冊商標,Sun 如今是 Oracle 旗下公司)。此次發佈後不久,Netscape 公司推出了服務器端 JavaScript 的實現,用於在 Netscape Enterprise Server 上運行腳本,並將其命名爲 LiveWire。① 1996 年,微軟在 IE3 中推出 JScript,即經過逆向工程實現的 JavaScript。JScript 在服務器端也能夠在互聯網信息服務器(IIS,Internet information server)中運行。正則表達式
①1998 年的這個小冊子(docs.oracle.com/cd/E19957-0…)詳細介紹了服務器端 JavaScript 以及 LiveWire 的方方面面。算法
1996 年,ECMA 的一個技術委員會 TC39 將 JavaScript 以名稱 ECMAScript(ES)標準化爲 ECMA-262 規範。爲何叫 ECMAScript 呢?由於 Sun 不一樣意將 JavaScript 商標轉讓給 ECMA,雖然微軟提議叫 JScript,但其餘成員公司又不想用,結果就只能使用 ECMAScript 這個尷尬的名字。npm
當時,TC39 開會主要就是爭論該採用 Netscape 的 JavaScript,仍是微軟的 JScript。儘管如此,該委員會仍是取得了成果,他們堅決不移地支持向後兼容,推進引入了嚴格相等運算符(===
和 !==
),不會影響依賴鬆散相等比較算法的現有程序。編程
ECMA-262 的初版於 1997 年 6 月發佈。次年 6 月,國際標準化組織對這個規範進行了完善和認真審查,並以 ISO/IEC 16262 的形式發佈,這就是它的第二版。
1999 年 12 月發佈的第三版標準化了正則表達式、switch
語句、do
/whille
、try
/catch
、Object#hasOwnProperty
,以及其餘一些特性。其中大部分特性已經能夠在 Netscape 的 JavaScript 運行環境 SpiderMonkey 中使用。
以後不久,TC39 發佈了 ES4 規範的草案。ES4 的早期工做直接致使了 2000 年年中 JScript.NET 的產生 ②,並最終促進 2006 年 Flash 中 ActionScript 3 的誕生。③
②能夠在微軟網站上找到最初的公告(2000 年 7 月)。
③Brendan Eich 在播客 JavaScript Jabber 中介紹了不少關於 JavaScript 起源的故事。
此時,關於 JavaScript 應該朝哪一個方向發展的不一樣意見致使了規範制定工做停滯不前。對於 Web 標準的發展而言,這時的情形很微妙:微軟幾乎壟斷了 Web 行業,卻對制定標準毫無興趣。
2003 年,AOL 裁掉了 50 名 Netscape 員工 ④,Mozilla 基金會隨之成立。同時,因爲微軟佔據了超過 95% 的 Web 瀏覽器市場份額,TC39 被迫解散。
④2003 年 7 月的 The Mac Observer 有該新聞的相關報道。
直到兩年後,Brendan 在 Mozilla 以 Firefox 日益增加的市場份額爲槓桿使得微軟迴歸,ECMA 才得以從新開始 TC39 的相關工做。2005 年年中,TC39 再次開始召開按期會議。對於 ES4,計劃引入模塊系統、類、迭代器、生成器、解構、類型註釋、尾調用優化、代數類型以及其餘各種功能。此次的新增內容過於龐大,致使 ES4 一次又一次地延期了。
2007 年,TC39 分裂爲兩派:一派主張推出 ES3.1,即只在 ES3 的基礎上完善改進;另外一派則主張推出 ES4,新特性繁多,且亟待規範化。直到 2008 年 8 月 ⑤,兩派才就 ES3.1 達成一致,ES3.1 後來又發展爲 ES5。ES4 的提議彷佛廢棄了,但實際上其中不少特性最終寫進了 ES6(達成和解時美其名曰 Harmony,即「和諧」),固然,其中一些特性還在討論,另外少數特性確實已經廢棄、被拒或撤銷。ES3.1 也爲 ES4 的逐步實現奠基了基礎。
⑤2008 年,Brendan Eich 給 es-discuss 發了一封郵件,其中介紹了當時的狀況,此時距 ES3 發佈都快 10 年了。
2009 年 12 月,ES3 發佈 10 週年,ECMAScript 第五版發佈。這一版聚集了當時瀏覽器中業已存在的擴展,或者說「事實標準」,增長了 get
和 set
存取器,加強了 Array
原型的函數特性,還引入了反射和內省機制,以及對 JSON 解析和嚴格模式的支持。
2011 年 6 月,通過再次審查和編輯,該規範造成了第三版的國際標準 ISO/IEC 16262:2011,並做爲 ECMAScript 5.1 發佈。
2015 年 6 月,TC39 又花 4 年完成了 ECMAScript 6。第六版是該語言面世以來改動最大的一個版本,實現了許多 ES4 中被推遲到 Harmony 中的提案。本書主要探討的就是 ES6。
在 ES6 的制定過程當中,另外一個旨在推進 Web 發展的組織 WHATWG(網頁超文本應用技術工做小組)於 2012 年推出了一個文檔,以記錄 ES5.1 和瀏覽器實如今兼容性和可操做性方面的差別。這個工做小組標準化了以前規範中沒有說起的 String#substr
,統一了在 HTML 標籤中包裝字符串的幾種方法,明確寫出了 Object.prototype
中的 __proto__
和 __defineGeter__
等原型屬性,同時還作出了其餘一些改進。⑥ 這些工做最終造成了一份獨立的 Web ECMAScript 規範,最終於 2015 年被加入到附錄 B 中。附錄 B 是 ECMAScript 核心規範中的參考部分,這意味着瀏覽器能夠不遵守其進行實現。這次更新以後,附錄 B 也成爲了 Web 瀏覽器的規範和要求。
⑥要想了解將 Web ECMAScript 規範合併到主幹時所作的所有更改,請參見 WHATWG 博客。
第六版是 JavaScript 歷史上一個意義重大的里程碑。除了衆多新功能以外,ES6 也是 ECMAScript 成爲持續迭代標準的一個轉折點。
ES3 在 10 年內未有重大改變,以後 4 年才推出 ES6。這一漫長曆程清楚地代表 TC39 流程須要改進。以前的修訂流程是最終發佈日期驅動的。只要有議題未能達成一致,下次修訂就會變得遙遙無期。時間一長又會有新的特性提出,進而致使更多拖延。小的修訂總會因大的新增而拖延,而大的新增迫於最終發佈日期的壓力,就會倉促經過修訂,以避免形成一拖再拖。
ES6 發佈後,TC39 優化了提案修訂的流程 ⑦,以知足現代預期:迭代具備常常性和一向性,且規範的制定要更加民主化。基於這一點,TC39 再也不採用古老的 Word 文檔形式,而是使用 Ecmarkup(用於編寫 ECMAScript 規範的 HTML 語言的超集)和 GitHub 來提交需求,大大增長了非成員的提案數量 ⑧,他們就像是外在的參與者同樣。這種新形式是持續的,而且更加透明:最新的規範草案隨時能夠查看,而無須像以前那樣,必須從網頁下載 Word 文檔或 PDF 版本。
⑦2013 年 9 月的 PPT,Post-ES6 Spec Process,介紹了優化後的提案修訂流程。
⑧TC39 採納的提案參見 mjavascript.com/out/tc39-pr…。
Firefox、Chrome、Edge、Safari 以及 Node.js 對 ES6 規範的支持均已超過 95%⑨。如今咱們就能夠在這些瀏覽器中使用已經支持的功能,而不用等到它們對 ES6 的支持度達到 100%。
⑨ES6 的瀏覽器兼容性報告參見 kangax.github.io/compat-tabl…。
新的流程引入了 4 個不一樣的成熟度階段。⑩ 提案越成熟,最終添加到規範中的可能性越大。
⑩TC39 的提案流程文檔參見 tc39.github.io/process-doc…。
只要還未做爲正式提案提交,關於修改或新增內容的任何討論、想法或者提議都會被視爲有前途的「稻草人」提案(階段 0),但只有 TC39 委員會的成員才能夠建立「稻草人」提案。在編寫本書時,有 10 多個活躍的「稻草人」提案。⑪
⑪「稻草人」提案參見 github.com/tc39/propos…。
階段 1 表示提案被正式提出,但願可以解決各方關注的問題,釐清與其餘提案的交集,並實現問題。這一階段的提案須要明確描述一個具體的問題,並給出該問題的具體解決方案。階段 1 的提案一般包括如下幾方面的內容:高級 API 描述、演示性的用法示例、內部語義和算法的討論。階段 1 的提案可能會隨着流程的推動而發生很大的改變。
階段 2 的提案是規範的初步草案。從這一步開始,須要在運行環境中驗證具體的實現。實現的方式能夠是膩子腳本(polyfill)、能讓運行環境支持提案的用戶代碼、原生支持提案內容的引擎實現,也能夠是使用構建工具將源代碼轉換、編譯成現有引擎能夠執行的代碼。
階段 3 的提案是候選推薦提案。只有規範的編輯和指定的審查人員在最終的規範上簽字確認,提案才能進入階段 3。另外,還須要實現者表示出對該提案感興趣。實際上,只有知足如下 3 個條件之一,提案才能進入階段 3:某個瀏覽器已經實現該提案,有高度吻合的膩子腳本,有相似 Babel 的實時編譯工具的支持。除了修復使用過程當中新發現的問題,階段 3 的提案不會再有其餘改動。
要想進入階段 4,提案必須有兩個獨立的實現方案經過驗收測試。進入階段 4 的提案最終會添加到 ECMAScript 的下一版中。
從如今開始,ECMAScript 預計每一年都會發布新版本。爲了與年度發版計劃統一,規範的版本從如今開始與出版的年份相關聯。所以,ES6 也就是 ES2015,以後將有 ES2016(而不是 ES7)、ES2017,等等。實際上,ES2015 這個稱呼並無被接受,你們仍是習慣稱其爲 ES6。ES2016 也是在命名約定改變前就發佈了的,所以有時人們也稱其爲 ES7。因爲 ES6 這一名稱已經爲社區廣泛接受,咱們拋開不談。最終的規範版本將是 ES六、ES201六、ES201七、ES2018,以此類推。
調整後的提案流程加上每一年都發布一版的強制約定造成了更加一致的發佈過程。這也意味着規範的修訂版本號變得再也不那麼重要。如今的重點是提案的不一樣階段,咱們相信未來你們會愈來愈少說起 ECMAScript 標準的某個特定修訂版。
若是可以有兩個 JavaScript 引擎提供獨立的實現,階段 3 的候選推薦提案最有可能進入下一個版本的規範之中。實際上,只要階段 3 的提案有實驗性的引擎實現或者膩子腳本,再或者能夠經過編譯器獲得支持,那麼就已經可以安全地在實際開發中使用了。其實,階段 2 和更早階段的提案也有爲 JavaScript 開發人員所使用的,這也增強了實現者和使用者之間的反饋循環。
Babel 等將代碼做爲輸入並生成 Web 平臺原生支持的輸出(HTML、CSS 或 JavaScript)的編譯器一般稱爲轉譯器(transpiler),它是編譯器的一個子集。若是咱們想要在代碼中使用某個 JavaScript 引擎尚未廣泛實現的提案,Babel 之類的編譯器能夠幫咱們將相應的代碼轉換成現有 JavaScript 實現能夠運行的代碼。
代碼轉換是在構建時完成的,所以用戶拿到的是本身的 JavaScript 運行環境所支持的代碼。這一機制下降了對運行環境的要求,也讓 JavaScript 開發者可以更早地使用新的語言功能和語法。對於規範的編寫者和實現者來講,這也是很是有利的,由於這樣他們就能夠獲得可行性、迫切性、可能存在的 bug,以及邊界用例等方面的反饋。
轉譯器能夠將 ES6 代碼轉換成瀏覽器廣泛能夠解釋的 ES5 代碼。這是現在在生產環境中運行 ES6 代碼的最可靠方式:經過構建生成 ES5 代碼,這樣新舊瀏覽器均可以執行。
這種方式一樣適用於 ES7 及後續版本。因爲語言規範每一年都會發布新版本,咱們能夠期待編譯器支持 ES2017 輸入、ES2018 輸入,等等。一樣,隨着瀏覽器的支持度愈來愈好,編譯器能夠逐漸下降支持 ES6 輸出、ES7 輸出的複雜性。從這種意義上說,咱們能夠將 JavaScript 轉譯器看做移動的窗口,其輸入是使用最新語法編寫的代碼,輸出是不影響瀏覽器運行的最新代碼。
接下來咱們探討如何在工做中使用 Babel。
Babel 能夠將 ES6 代碼編譯成 ES5 代碼。生成的 ES5 代碼很容易看懂,所以很是適合還不徹底熟悉新特性的人來理解新特性。
Babel 的在線讀取 - 求值 - 打印循環(REPL,read-evaluate-print loop)轉換器是學習 ES6 的好幫手,無須安裝 Node.js、babel
CLI,也無須手工編譯源碼。
REPL 提供了一個源碼輸入框,用於自動實時編譯,編譯後的代碼位於源碼右側。
咱們能夠在 REPL 中寫幾行代碼,以下所示。
var double = value => value * 2
console.log(double(3))
// <- 6複製代碼
咱們能夠在右側看到轉換後的 ES5 等價代碼,如圖 1-1 所示。更新源碼時,轉譯結果也會實時更新。
圖 1-1:在線 Babel REPL 是交互式學習 ES6 的好工具
Babel REPL 也是用於試驗本書中介紹的一些特性的有效工具。但須要知道的是,Babel 並不轉換新的內置對象,如 Symbol
、Proxy
和 WeakMap
。這些引用會原封不動地保留下來,最終由執行 Babel 輸出代碼的運行環境提供這些內置對象。若是想要支持尚未實現這些內置對象的運行環境,能夠在代碼中引入 babel-polyfill
包。
在一些較老的 JavaScript 版本中,想要語義正確地實現某些特性是很難的,甚至徹底不可能。此時能夠用膩子腳本彌補這個問題,但膩子腳本一般不能覆蓋全部狀況,所以須要作一些妥協。因此,在將轉譯後的使用了內置對象和膩子腳本的代碼發佈到生產環境以前,最好多作一些測試。
考慮到這種狀況,最好仍是等瀏覽器總體支持這些新的內置對象時再使用它們。咱們建議你使用不依賴於這些新內置對象的替代方案。與此同時,學習這些特性也很重要,這樣咱們對 JavaScript 語言的理解纔不會落後。
Chrome、Firefox 和 Edge 等現代瀏覽器如今已經支持 ES2015 及後續版本的大部份內容,因此在支持的前提下,能夠經過它們的開發者工具來嘗試新特性。產品級應用須要依賴新 JavaScript 特性時,仍是推薦使用轉換器進行編譯處理,這樣應用可以支持更多的 JavaScript 運行環境。
除了 REPL,Babel 還提供了一個在命令行中運行的 Node.js 包,能夠經過 Node.js 的包管理工具 npm
來安裝它。
下載 Node.js。安裝
node
後,就能夠在終端內使用npm
命令了。
開始以前,咱們先建立一個項目目錄以及一個用於描述 Node.js 應用的 package.json 文件。能夠經過 npm
在命令行中建立 package.json 文件。
mkdir babel-setup
cd babel-setup
npm init --yes複製代碼
執行
init
命令時傳遞--yes
參數表示不用詢問咱們,可使用npm
提供的默認值來配置 package.json 文件。
再建立一個 example.js 文件,並在其中加入如下代碼,而後將其保存到剛剛建立的 babel- setup 目錄下的 src 子目錄。
var double = value => value * 2
console.log(double(3))
// <- 6複製代碼
在經常使用的終端中輸入如下兩行命令便可安裝 Babel。
npm install babel-cli@6 --save-dev
npm install babel-preset-env@6 --save-dev複製代碼
經過
npm
安裝的包存放於項目根目錄的 node_modules 目錄下。能夠經過建立npm script
命令或使用require
聲明來訪問這些包。
--save-dev
參數會將所安裝的包做爲開發依賴添加到 package.json 文件中。這樣一來,當咱們將項目移植到一個新環境時,只須運行npm install
命令就能夠從新安裝每一個依賴。
@
符號指明瞭包的特定版本。使用@6
則是告訴npm
安裝babel-cli
的6.x
版本中最新的一個。這種偏好限制能夠確保咱們的應用未來不出問題,由於它能夠確保永遠不會安裝7.0.0
或後續版本,從而避免了7.0.0
以後的版本包含當前沒法預見的破壞性變化。
接下來,咱們修改 package.json 中的 scripts
屬性的值,以下所示。babel-cli
提供的 babel
命令行工具能夠獲取 src 目錄下的所有內容,將它們編譯成目標輸出格式,並將結果保存到 dist 目錄中,而且保留文件的原始目錄結構。
{
"scripts": {
"build": "babel src --out-dir dist"
}
}複製代碼
加上前面安裝的包,如今咱們構成了如下這個超小的 package.json 文件。
{
"scripts": {
"build": "babel src --out-dir dist"
},
"devDependencies": {
"babel-cli": "^6.24.0",
"babel-preset-env": "^1.2.1"
}
}複製代碼
scripts
對象中列舉的全部命令均可以經過npm run <name>
執行,這種執行方式會臨時修改環境變量$PATH
的值,這樣咱們才能夠在系統未全局安裝babel-cli
的狀況下找到babel-cli
並在命令行執行。
若是如今在終端內執行 npm run build
,你就能看到生成後的 dist/example.js 文件。輸出的文件和源文件徹底相同。這是由於 Babel 還不知道編譯的目標格式,咱們須要先配置它。在 package.json 旁建立一個 .babelrc 文件,並在其中寫入如下 JSON。
{
"presets": ["env"]
}複製代碼
這裏的 env
就是前面經過 npm
安裝的 babel-preset-env
,它給 Babel 添加了一系列插件,以便將不一樣的 ES6 代碼轉換爲 ES5。這個預設包含不少插件,其中就有插件將 example.js 中的箭頭函數轉換成 ES5 代碼。env
預設會根據最新瀏覽器已經支持的特性啓用相關的轉換插件。這個預設是可配置的,咱們能夠決定向後兼容到哪一個瀏覽器。兼容的瀏覽器越多,編譯生成的包就越大;兼容的瀏覽器越少,能知足的用戶就越少。固然,到底什麼配置最合適,最終仍是要通過研究才能決定。默認配置是啓用全部轉換插件,兼容儘量多的運行環境。
再運行一次編譯腳本就可以看到輸出的 ES5 代碼了。
» npm run build
» cat dist/example.js
"use strict"
var double = function double(value) {
return value * 2
}
console.log(double(3))
// <- 6複製代碼
接下來咱們再介紹一個代碼檢查工具 eslint
,它能夠幫助咱們確保項目代碼的質量。
開發項目時,咱們會發現冗餘或無用的代碼,編寫不少新代碼,刪除無關或不必的功能,也會爲適應新架構而來回搬運代碼。隨着代碼越寫越多,團隊規模也會隨之變化。剛開始可能只有幾我的,甚至只有一我的,但隨着項目規模愈來愈大,參與編碼的人也會愈來愈多。
代碼檢查工具能夠幫助咱們發現語法錯誤。現代檢查工具一般都是可定製的,容許咱們創建適合本身團隊的代碼約定。堅守一致的代碼風格和質量基準可使團隊的編碼風格趨於一致。不一樣的團隊成員可能會對代碼風格有不一樣的意見,但有了代碼檢查工具和協商一致的配置後,這些意見就變成了明確可遵循的規則。
首先是確保程序能被解析,其次可能要防止 throw
拋出字符串字面量做爲異常,或者不容許在生產環境中使用 console.log
和 debugger
語句。然而,要求全部函數調用都只能有一個參數就有點過了。
雖然代碼檢查工具可以定義並強制推行一種編碼風格,但定義規則時也不能太任性。若是規則太嚴格,可能會影響開發效率,得不償失。反之,規則太寬鬆的話,代碼就不能保持統一風格。
要想把握好這個度,就應該儘可能不使用多數狀況下都不能改善程序的規則。新增一條規則時,應當捫心自問,添加它可否顯著改善現有代碼庫以及將來的新代碼?
ESLint 是一個現代代碼檢查工具,它集合了一些插件,具備不一樣的規則,支持自定義。咱們能夠決定不遵照規則時是輸出警告仍是致使停機錯誤。與安裝 babel
同樣,咱們也能夠經過 npm
安裝 eslint
。
npm install eslint@3 --save-dev複製代碼
接下來咱們須要配置 ESLint。由於本地安裝了 eslint
,因此能夠在 node_modules/.bin 中找到它的命令行工具。執行如下命令可以引導咱們配置 ESlint。首先,告訴它咱們想使用一套流行的風格,而後選擇 Standard⑫,最後選擇 JSON 格式的配置文件。
⑫注意,Standard 是一種自我宣告,並未由任何官方組織進行實際的標準化。其實,只要可以保持統一,使用哪一種風格並不重要。在閱讀項目代碼時,一致性有助於減小困擾。Airbnb 風格指南也是很受歡迎的,與 Standard 不一樣,它默認不可省略分號。
./node_modules/.bin/eslint --init
? How would you like to configure ESLint?
Use a popular style guide
? Which style guide do you want to follow? Standard
? What format do you want your config file to be in? JSON複製代碼
除了個別規則,eslint
還支持擴展預約義規則,這些規則以 Node.js 包的形式存在。在多項目甚至社區中共享配置時,這會很方便。選擇 Standard 後,能夠看到 ESLint 向 package.json 中添加了一些依賴,即包含預設 Standard 規則的包,同時建立了一個名爲 .eslintrc.json 的文件,其中包含如下內容。
{
"extends": "standard",
"plugins": [
"standard",
"promise"
]
}複製代碼
直接引用包含 npm
實現細節的 node_modules/.bin 目錄並很差。雖然前面初始化 ESLint 配置時這麼引用了,但其實應該避免這樣作,並且檢查代碼時也不該該每次都那麼輸入一遍。爲此,咱們在 packge.json 中添加一個腳本命令。
{
"scripts": {
"lint": "eslint ."
}
}複製代碼
前面安裝 Babel 時提到過,npm run
在執行腳本命令時會將 node_modules 加入 PATH
環境變量。這樣一來,在檢查代碼時,只要執行 npm run lint
,npm
就會在 node_modules 目錄中找到 ESLint CLI。
咱們來看看如下的示例文件 example.js,其中的代碼故意沒有遵照規則,以演示 ESLint 具體作了什麼。
var goodbye='Goodbye!'function hello(){ return goodbye}
複製代碼if(false){}複製代碼
執行 lint
腳本命令時,ESLint 會標識文件中全部錯誤的地方,如圖 1-2 所示。
圖 1-2:ESLint 能夠幫助咱們檢查語法錯誤,保持代碼風格統一
若是在執行命令時傳遞 --fix
參數,那麼 ESLint 可以自動修復大多數的風格問題。在 package.json 中加入如下腳本命令。
{
"scripts": {
"lint-fix": "eslint . --fix"
}
}複製代碼
此時執行 lint-fix
只會看到兩個錯誤:未使用 hello
以及 false
是一個不變的條件。其餘錯誤都已經修復了,結果如如下代碼所示。上述兩個錯誤沒有修復,由於 ESLint 會保持中立,不對代碼語義作預設推斷,以避免致使語義改變。這樣一來,--fix
就能幫助咱們有效解決編碼風格問題,同時又不會破壞邏輯。
var goodbye = 'Goodbye!'function hello() { return goodbye }
複製代碼if (false) {}複製代碼
prettier
也是一種代碼檢查工具,可用於自動格式化代碼。咱們能夠配置prettier
自動重寫代碼,以確保代碼遵循設定的首選項,如使用給定的空格縮進,統一使用單引號或雙引號,末尾自動加逗號,或者限制最大行長度。
如今咱們知道了如何將現代 Javascript 代碼編譯成每一個瀏覽器都能理解的代碼,以及如何正確檢查和格式化代碼。接下來概述一下 ES6 的特性,並展望一下 JavaScript 的將來。
ES6 規範足足有 566 頁,是 ES5.1 規範 258 頁的兩倍多。ES6 的主要變化能夠概括爲如下幾類:
語法糖是 ES6 中最重要的組成部分,包括用新類來表達對象繼承、箭頭函數以及屬性值簡寫等一系列更簡潔的語法。此外,解構、剩餘參數以及擴展運算符等咱們將介紹的特性也提供了更加語義化的編程方式。第 2 章和第 3 章將介紹 ES6 中的這部份內容。
ES6 提供了幾種新機制來描述異步流程:表明一個操做最終結果的 Promise、表明一系列值的迭代器,以及能產生一系列值的特殊迭代器——生成器。基於這些新概念和結構,ES2017 提供了 async
/await
,讓咱們能夠像編寫同步代碼那樣編寫異步代碼。第 4 章將介紹這裏提到的迭代及流控制機制。
在 JavaScript 中,使用任意字符串做爲鍵的普通對象來建立映射是很常見的。若是鍵值來自用戶輸入,且沒有驗證,那麼極有可能產生漏洞。爲此,ES6 引入了一些新的原生內置對象來管理集合和映射,而且沒有隻能使用字符串做爲鍵的限制。第 9 章將介紹相關內容。
代理對象用於從新定義能夠經過 JavaScript 反射完成的操做。代理對象和其餘語境中的代理相似,好比網絡路由中所說的代理。它能夠攔截 JavaScript 對象的任何交互,好比屬性的定義、刪除以及訪問。鑑於代理的工做機制,咱們很難用膩子腳本全面實現其功能:固然,膩子腳本是有的,只是在某些場景下其實現與規範不符。第 6 章將介紹代理。
除了新的內置對象,ES6 還對 Number
、Math
、Array
以及 String
對象進行了必定的擴展。第 7 章將介紹添加在這些內置對象上的一系列新實例方法和靜態方法。
ES6 還爲 JavaScript 引入了一個原生模塊系統。第 8 章從 Node.js 使用的 CommonJS 模塊系統講起,而後詳細講解 JavaScript 原生模塊的語義。
由於 ES6 引入了太多修改,因此很難作到將其新特性與現有 JavaScript 知識天然整合。爲此,第 9 章將用一整章的篇幅來分析每一個特性的優勢和重要性,以便你對 ES6 創建起初步的概念,並基於此開始使用 ES6。
JavaScript 語言已經從 1995 年一門沒啥名氣的語言發展爲今天這樣一門強大的語言。雖然 ES6 向前跨越了一大步,卻遠遠未到終點。鑑於每一年都會有新的規範發佈,如何跟上新規範發佈的步伐就很重要了。
瞭解 1.2 節中介紹的持續迭代流程後,咱們知道,要想跟進標準,首先就要按期訪問 TC39 提案庫 ⑬。咱們要時刻關注候選推薦提案(即階段 3 的提案),由於這些提案最有可能加入新規範。
⑬TC39 收錄的全部提案參見 mjavascript.com/out/tc39-pr…。
用一本書來介紹一門快速發展的語言是不太可能的。所以,關注 TC39 提案庫、訂閱週刊 ⑭、閱讀 JavaScript 博客 ⑮ 是及時跟進 JavaScript 最新進展的有效方式。
⑭這種電子週刊不少,如 Pony Foo Weekly、Javascript Weekly。
⑮Pony Foo 網站上有不少關於 ECMAScript 開發的文章,Axel Rauschmayer 也寫了不少關於這方面的文章。
撰寫本書時,開發者期待已久的 Async 函數已經加入規範,並在 ES2017 中發佈。此時此刻有不少候選提案,好比支持異步加載原生 JavaScript 模塊的動態 import()
,以及使用 ES6 中針對參數列表和數組引入的剩餘和擴展運算符來枚舉對象屬性。
雖然本書的主要關注點是 ES6,但咱們一樣會學習重要的候選推薦,如剛剛說起的 Async 函數、動態 import()
調用、對象剩餘 / 擴展,以及其餘內容。