ES6相關新特性介紹

你可能已經據說過 ECMAScript 6 (簡稱 ES6)了。ES6 是 Javascript 的下一個版本,它有不少很棒的新特性。這些特性複雜程度各不相同,但對於簡單的腳本和複雜的應用都頗有用。在本文中,咱們將討論一些精心挑選的 ES6 特性,這些特性能夠用於你平常的 Javascript 編碼中。html

請注意,當前瀏覽器已經全面展開對這些 ES6 新特性的支持,儘管目前的支持程度還有所差別。若是你須要支持一些缺乏不少 ES6 特性的舊版瀏覽器,我將介紹一些當前能夠幫助你開始使用 ES6 的解決方案。node

文中大多數代碼示例都帶有「運行代碼」連接,你能夠查看代碼並運行它。git

變量

LET

你習慣於用 var 聲明變量。如今你也能夠用 let 了。二者微妙的差異在於做用域。var 聲明的變量做用域爲包圍它的函數,而 let 聲明的變量做用域僅在它所在的塊中。 es6

這樣使得代碼更加乾淨,減小滯留的變量。看看如下經典的數組遍歷:github

舉個例子,一般狀況下,咱們在同一做用域裏使用變量 j 來完成另外一個遍歷。可是,如今有了 let,能夠安全地再一次聲明 i 變量。由於它只在被聲明的塊中有效。web

CONST

還有另外一個用於聲明塊做用域變量的方法。使用 const,你能夠聲明一個值的只讀引用。必須直接給一個變量賦值。若是嘗試修改變量或者沒有當即給變量賦值,都將報錯:typescript

注意,對象的屬性或數組成員仍是能夠改變的。npm

箭頭函數

箭頭函數爲 Javascript 語言增色很多。它使得代碼更簡潔。咱們早早地在本文中介紹箭頭函數,這樣就能夠在後面的示例中加以利用了。如下代碼片斷是箭頭函數和咱們熟悉的 ES5 版本的寫法:gulp

運行代碼數組

若是咱們觀察箭頭函數的語法,會發現其中並無出現 function 關鍵詞。只保留零或多個參數,「胖箭頭」(=>)和函數表達式。return 聲明被隱式加入。

帶有零或多個參數時,必須使用括號:

若是須要寫更多的邏輯或更多的空格,能夠把函數表達式放在({...})塊中。

運行代碼

箭頭函數不單只是爲了輸入更少的字符,它們的表現也和通常函數不一樣。它繼承了當前上下文的 this 和 arguments。這就意味着,你能夠避免寫 var that = this 這樣醜陋的代碼,也不須要把函數綁定到正確的上下文了。舉例以下(注意對比 this.title 和 ES5 版本的 that.title 的不一樣): 

運行代碼

字符串

方法

幾個方便的方法被添加到 String 的原型中。其中大多數用於簡化須要用 indexOf() 方法來解決的問題的複雜度,並達到一樣的效果:

很簡單可是頗有效。添加了另一個方便的用於建立重複字符串的方法:

模板字符串

模板字符串提供一個簡潔的方式來實現字符串插值。你可能已經對這種語法很熟悉了;它基於美圓符號和花括號 ${..}。模板字符串置於引號之中。如下是快速示例:

運行代碼

以上形式對比 ES5 僅僅是便於字符串拼接。事實上,模板字符串還能夠用於多行字符串。記住空格也是字符串的一部分。 

運行代碼

數組

Array 對象增長了一些新的靜態方法,Array 原型上也增長了一些新方法。

首先, Array.from 從類數組和可遍歷對象中建立 Array 的實例。類數組對象示例包括:

  • 函數中的 arguments
  • 由 document.getElementByTagName() 返回的 nodeList
  • 新增長的 Map 和 Set 數據結構。 

運行代碼

在上面的例子中,能夠看到 items 數組擁有 forEach 方法,該方法是 itemElements 集合所不具有的。

Array.from 的一個有趣的特性是它的第二個可選參數mapFunction 。該參數容許你經過一次單獨調用建立一個新的映射數組。

運行代碼

而後,咱們可使用 Array.of 方法,該方法的表現很像 Array 構造函數。它適合只傳遞一個參數的狀況。所以 Array.of 是 new Array() 的更優選擇。然而,更多的狀況下,你會想使用數組字面量。

  • find 返回回調返回 true 的第一個元素。
  • findIndex 返回回調函數返回 true的第一個元素的下標。
  • fill 用所給參數「覆蓋」數組的元素。

Math

Math 對象新增了幾個方法。

  • Math.sign 返回數字的符號,結果爲 1-1 或 0
  • Math.trunc 返回無小數位的數字。
  • Math.cbrt 返回數字的立方根。

若是你想學習更多 ES6 中的 number 和 math 新特性, Dr. Axel Rauschmayer將爲你解答。

擴展操做符

擴展操做符(...)這個語法用於特定地方擴展元素很是方便,例如函數調用中的參數。讓你瞭解它們用途的最好方法就是舉例子了。

首先,咱們看看如何在一個另數組中擴展一個數組的元素。

運行代碼

擴展語法在傳參數調用函數時也很是有用:

正如你所看到的,該語法讓咱們免去一般使用 fn.apply() 的麻煩。它很是靈活,由於擴展操做符能夠用在參數列表中的任意位置。這意味着如下調用方式會產生同樣的結果: 

咱們已經把擴展操做符應用在數組和參數中。事實上,它能夠用在全部的可遍歷對象中,例如一個 NodeList

如今, allTheThings 是一個包含 <form> 節點、 <input> 子節點和 <select> 子節點的二維數組。

解構

解構提供了一個方便地從對象或數組中提取數據的方法。對於初學者,請看如下數組示例:

使用這個語法,能夠一次性給多個變量賦值。一個很好的附加用處是能夠很簡單地交換變量值:

解構也能夠用於對象。注意對象中必須存在對應的鍵:

JavaScript

運行代碼

你也可使用該機制來修改變量名:

JavaScript

另外一個有趣的模式是模擬多個返回值:

運行代碼

解構能夠用來爲參數對象賦默認值。經過對象字面量,能夠模擬命名參數:

默認值

在 ES6 中,能夠定義函數的參數默認值。語法以下:

看起來很簡潔,對吧? 我確定你以前在 ES5 中曾經須要給某些參數賦默認值:

傳遞 undefined 或不傳參數時都會觸發參數使用默認值。

REST參數

咱們已經學習了省略號操做符。剩餘參數和它很相似。它一樣是使用 ... 語法,容許你把末尾的參數保存在數組中:

模塊

模塊固然是一個受歡迎的 Javascript 語言新功能。我想僅僅是這個主要特性就值得咱們投入到 ES6 中來。

當前任何重要的 Javascript 項目都使用某種模塊系統 —— 多是「展現模塊模式」或其餘 AMD 或 CommonJS 擴展形式的東西。然而,瀏覽器並無任何模塊系統特性。爲了實現 AMD 或 CommonJS,你一般須要一個構建步驟或加載器。解決這個問題的工具包括 RequireJS、Browserify 和 WebPack。

ES6 規範包含模塊化的新語法和加載器。若是你將來想使用模塊,應該使用這個語法。現代構建工具支持這種形式(可能經過插件),因此你能夠放心使用。(不用擔憂 —— 咱們將在後面的「轉譯」章節中討論)

在 ES6 的模塊語法中。模塊設計圍繞 export 和 import 關鍵詞。如今讓咱們看一個包含兩個模塊的例子:

正如你所見,能夠存在多個 export 聲明。每個都要明確地指明輸出值的類型(本例中的function 和 var)。

本例中的 import 聲明使用一種語法(相似解構)來明肯定義被導入的內容。可使用 * 通配符,結合 as 關鍵詞給模塊提供一個本地名稱,把模塊當成一個總體導入。 

模塊系統有一個 default 輸出。它能夠是一個函數。只須要提供一個本地名稱就能夠導入這個默認值(即無解構): 

請注意 import 聲明是同步的,可是模塊代碼需在全部依賴加載完後纔會運行。

類是 ES6 中備受熱議的一個特性。一部分人認爲它不符合 Javascript 的原型特性,另外一部分人認爲類能夠下降從其餘語言轉過來的入門門檻,並幫助人們構建大規模應用。無論怎樣,它是 ES6 的一部分。這裏咱們快速介紹一下。

類的建立圍繞 class 和 constructor 關鍵詞。如下是個簡短的示例:

運行代碼

注意類的定義不是通常的對象,所以,類的成員間沒有逗號。

創造一個類的對象時,須要使用 new 關鍵詞。繼承一個基類時,使用 extends

運行代碼

從衍生類中,你可使用從任何構造函數或方法中使用 super 來獲取它的基類:

  • 使用 super() 調用父類構造函數。
  • 調用其它成員,舉個例子,使用 super.getName() 。

還有更多關於類的內容。若是你想深刻了解,我推薦 Dr.Axel Rauschmayer 的 《Classes in ECAMScript 6》

記號

記號是一個新的原生數據類型,像 Number 和 String 同樣。你可使用記號爲對象屬性建立惟一標識或建立惟一的常量。

記號與 const 配合很合適,由於它們都有不可改變的特性。

你能夠爲 symbol 添加描述。雖然不能夠經過描述獲取 symbol,可是可用於代碼調試。 

想學習更多關於 symbols 的內容嗎?Mozilla 開發者網絡有一個關於該新的 symbol primitive的文章。

轉譯

咱們如今能夠用 ES6 來寫代碼了。正如介紹中提到的,瀏覽器對 ES6 特性的支持尚不普遍,且各瀏覽器也各不相同。頗有可能你寫的的代碼在用戶的瀏覽器中不能徹底解析。這就是咱們爲何須要把代碼轉換成能在當前的任何瀏覽器中良好運行的舊版本 Javascript(ES5) 。這種轉換一般稱爲「轉譯」。咱們必須在應用中這麼作,直到全部咱們想兼容的瀏覽器都能運行 ES6 爲止。

入門

轉譯代碼並不難。你能夠經過命令行直接轉譯代碼,也能夠把它做爲 Grunt 或 Gulp 之類的任務管理器的插件包含進來。有不少轉譯解決方案,包括 Babel,Traceur 和 TypeScript。例如, 經過 Babel(以前的 「6to5」) 開始使用 ES6 的多種方式 。大多數 ES6 特性供你自由使用。

既然你對 ES6 充滿熱情和期待,爲何不開始使用它呢。根據你想使用的特性和須要兼容的瀏覽器或環境(好比 Node.js),你可能須要在工做流中引入轉譯器。若是你肯定要使用它們,文件監聽器和瀏覽器動態刷新器可使你的編碼體驗更加流暢。

若是你是從零開始,你可能只想經過命令行轉譯代碼(能夠從 Babel CLI documentation 查看示例)。若是你已經使用任務運行器,如 Grunt 或 Gulp,你能夠添加相似 gulp-babel 或Webpack babel-loader 的插件。對於 Grunt,可以使用 grunt-babel 和不少其餘 ES6 相關 的插件。Browserify 的用戶可能會想看看 babelify 

大多數特性能夠被轉換成兼容 ES5 的代碼且開銷很小。其餘的特性則須要額外處理(可由轉譯器提供),可能有性能損失。若是想把玩一下 ES6 並查看轉譯後的代碼的樣子,可使用各類交互環境(也就是 REPL):

注意 TypeScript 不徹底是一個轉譯器。它是一個類型化的 Javascript 超集,編譯成 Javascript 代碼。在其它特性中,它支持不少 ES6 特性,很像其餘編譯器。

因此,我究竟能夠用什麼?

總的來講,部分 ES6 特性幾乎是能夠「免費」使用的,好比模塊,箭頭函數,剩餘參數和類。這些特性只需很小的開銷就能夠被轉譯成 ES5 。ArrayString 和 Math 對象和原型的附加方法(如 Array.from() 和 "it".startsWith("you"))須要所謂的「polyfills」。Polyfills 是瀏覽器未原生支持的功能的臨時補充。你能夠先加載 profill,而後你的代碼就能夠在瀏覽器中運行,彷彿瀏覽器有這個功能同樣。Babel 和 Traceur 都提供這種 polyfills。

可在Kangax 的 ES6 兼容性表格 中查看轉譯器和瀏覽器支持的 ES6 特性的完整概述。在寫本文時,最新的瀏覽器已經支持 55% 到 70% 以上 ES6 特性了,看到這個真是鼓舞人心啊。Microsoft Edge、Google Chrome 和 Mozilla 的 Firefox 已經在這方面相互競爭了,這對 web 技術整體來講是很是好的。

就我的而言,能夠輕鬆地使用模塊、箭頭函數和剩餘參數之類的 ES6 新特性對於個人代碼是一個極大的提升,是生產力的解放。既然我已經習慣了寫 ES6 代碼並轉譯成 ES5,隨着時間的推移,更多的 ES6 的好處將會天然顯現。

接下來呢?

一旦你安裝了轉譯器,你可能新從 let 和箭頭函數之類的「小」特性開始使用。記住本來就是用 ES5 寫的代碼將不會被轉譯器轉譯。當你使用 ES6 來提升你的代碼,而且喜歡它時,你能夠逐漸往你的代碼中添加更多的 ES6 特性。或者把部分代碼轉換成新模塊或類語法。我保證這樣會很爽!

ES6 的內容比本文中所涉及的多得多。未涉及的特性包括 MapSet、標籤模板字符串、生成器、Proxy 和 Promise。讓我知道你是否但願下篇文章涉及這些特性。無論怎樣,我很高興推薦 Axel Rauschmayer 博士寫的覆蓋全部 ES6 特性的《Exploring ES6》供深刻研究。

結語

當瀏覽器不斷添加新特性時, 經過使用轉譯器,你的全部代碼被有效地「鎖定」到 ES5 。因此,就算瀏覽器徹底支持了某一個 ES6 特性,兼容 ES5 的版本將被使用,可能會性能更差。你能夠期望在某個點(在當時你須要兼容的瀏覽器和環境)上全部的 ES6 特性最終被支持。到那時,咱們須要管理它們,選擇性地防止 ES6 特性轉譯成 ES5,以減小性能開銷。考慮這個因素,判斷當前是不是開始使用(部分)ES6 的時候。部分公司認爲是這樣

相關文章
相關標籤/搜索