JS 開發者必須知道的十個 ES6 新特性


這篇文章會給你簡單介紹一下ES6。如果你還不知道什么是ES6的話,它是JavaScript一個新的實現,如果你是一個忙碌的JavaScript開發者(但誰不是呢),那么繼續讀下去吧,看看當今最熱門的語言——JavaScript的新一代實現中,最棒的十個特性。

這是為忙碌的開發者准備的ES6中最棒的十個特性(無特定順序):

  1. 默認參數
  2. 模版表達式
  3. 多行字符串
  4. 拆包表達式
  5. 改進的對象表達式
  6. 箭頭函數 =&>
  7. Promise
  8. 塊級作用域的letconst
  9. 模塊化

注意:這個列表十分主觀並且帶有偏見,其他未上榜的特性並不是因為沒有作用,我這么做只是單純的希望將這份列表中的項目保持在十個。

首先,一個簡單的JavaScript時間線,不了解歷史的人也無法創造歷史。

  1. 1995年:JavaScript以LiveScript之名誕生
  2. 1997年:ECMAScript標准確立
  3. 1999年:ES3發布,IE5非常生氣
  4. 2000年-2005年:XMLHttpRequest,熟知為AJAX,在如Outlook Web Access(2002)、Oddpost(2002)、Gmail(2004)、Google Maps(2005)中得到了廣泛的應用
  5. 2009年:ES5發布(這是我們目前用的最多的版本),帶來了forEach / Object.keysObject.create(特地為Douglas Crockford所造,JSON標准創建者) ,還有JSON標准。

歷史課上完了,我們回來講編程。

1. ES6中的默認參數

還記得我們以前要這樣子來定義默認參數:

這樣做一直都沒什么問題,直到參數的值為0,因為0在JavaScript中算是false值,它會直接變成后面硬編碼的值而不是0本身。當然了,誰要用0來傳值啊(諷刺臉)?所以我們也忽略了這個瑕疵,沿用了這個邏輯,否則的話只能…..沒有否則!在ES6中,我們可以把這些默認值直接放在函數簽名中。

對了,這個語法和Ruby很像!

2. ES6中的模版表達式

模版表達式在其他語言中一般是為了在模版字符串中輸出變量,所以在ES5中,我們非得把字符串破開變成這樣:

幸運的是在ES6中我們有了新語法,在反引號包裹的字符串中,使用${NAME}語法來表示模板字符:

 

3. ES6中的多行字符串

另一個好吃的語法糖就是多行字符串,以前我們的實現是像這樣的:

但是在ES6中,只要充分利用反引號。

 

4. ES6中的拆包表達式

拆包可能是一個比較難理解的概念,因為這里面真的是有魔法發生。假如說你有一個簡單的賦值表達式,把對象中的housemouse賦值為housemouse的變量。

另一個拆包的實例(Node.js):

但是在ES6中我們可以用以下語句替換:

甚至在數組中也能用,簡直瘋狂!

習慣拆包語法可能需要一些時間,但是這絕對是糖衣炮彈。

5. ES6中改進的對象表達式

你能用對象表達式所做的是超乎想象的!類定義的方法從ES5中一個美化版的JSON,進化到ES6中更像類的構造。

這是一個ES5中典型的對象表達式,定義了一些方法和屬性。

如果你想做的好看一點,我們可以用Object.create方法來讓 serviceBase 成為 accountServiceES5 的 prototype 從而實現繼承。

我知道 accountServiceES5ObjectCreate 和 accountServiceES5 不完全相同的。因為一個對象 accountServiceES5 會有如下所示的 __proto__ 屬性:

但對於這個示例,我們就把這兩者考慮為相同的。所以在ES6的對象表達式中,我們把getAccounts: getAccounts簡化為getAccounts,,並且我們還可以用__proto__直接設置prototype,這樣聽起來合理的多。(不過並不是用proto

還有,我們可以調用 super 和動態索引(valueOf_1_2_3)

這是對老舊的對象表達式一個很大的改進!

6. ES6中的箭頭函數

這或許是我最想要的一個特性,我愛 CoffeeScript 就是因為他胖胖的箭頭(=&>相對於-&>),現在ES6中也有了。這些箭頭最神奇的地方在於他會讓你寫正確的代碼。比如,this在上下文和函數中的值應當是相同的,它不會變化,通常變化的原因都是因為你創建了閉包。

使用箭頭函數可以讓我們不再用that = this或者self = this或者_this = this或者.bind(this)這樣的代碼,比如,這些代碼在ES5中就特別丑。

這是在ES6中去掉_this = this之后:

可惜的是,ES6委員會覺得再加上瘦箭頭(-&>)的話就對我們太好了,所以他們留下了一個老舊的function。(瘦箭頭在CoffeeScript中的作用就像ES5/6中一樣)

在ES6中我們無需_this

注意,在ES6中你可以合理的把箭頭函數和舊式 function 函數混用。當箭頭函數所在語句只有一行時,它就會變成一個表達式,它會直接返回這個語句的值。但是如果你有多行語句,你就要明確的使用return

這是ES5中利用messages數組創建一個數組的代碼:

在ES6中會變成這樣:

注意到我用了字符串模版嗎,又一個從CoffeeScript中來的功能,我愛它們!

在只有一個參數的函數簽名中,括號是可有可無的,但是如果多於一個參數時就要加上。

 

7. ES6中的Promise

Promise是一個有爭議的話題。現在有很多Promise實現,語法也大致相同,比如qbluebirddeferred.jsvowavowjquery deferred等等。其他人說我們並不需要Promise,異步,回調和generator之類的就很好。慶幸的是,現在在ES6中終於有一個標准的Promise實現。

我們來看一個相當微不足道的延遲異步執行,用setTimeout實現

我們可以用ES6中的Promise重寫:

或者用ES6的箭頭函數:

到現在為止,我們只是單純增加了代碼的行數,還明顯沒有帶來任何好處,你說的對。但是如果我們有更多復雜的邏輯內嵌在setTimeout()中的回調時好處就來了:

可以用ES6中的Promise重寫:

還是無法相信Promise比普通回調要好?我也不信。我想一旦知道了回調這個方法它就會在你腦中縈繞,額外的復雜的Promise也沒有必要存在了。

不論怎么說,ES6中的Promise是為會欣賞的人准備的,Promise有一個不錯的失敗-捕捉回調機制,看看這篇文章吧,里面有更多關於Promise的信息。ES6 Promise介紹

8. 塊級作用域的letconst

你可能早就聽過對ES6中的let那些奇怪的傳說,我記得我第一次到倫敦時為那些TO LET牌子感到非常困惑。但是ES6中的let和出租無關,這不算是語法糖,它很復雜。let是一個更新的var,可以讓你把變量作用域限制在當前塊里。我們用{}來定義塊,但是在ES5中這些花括號起不到任何作用。

運行結果將會是1000。天啊!這是多大的一個Bug。在ES6中,我們用let來限制變量作用域為函數內。

運行結果是0,因為在if塊中也有let。如果什么都沒有的話(amount=1),那么結果將會是1

說到const,事情就簡單多了。他僅僅產生是一個不可變的變量,並且他的作用域也像let一樣只有塊級。為了演示,這里有定義了一堆常量,並且由於作用域的原因,這些定義都是有效的。

依我愚見,letconst讓這門語言變得更加復雜,沒有這些的時候我們只有一條路可以走,但是現在可以要考慮更多的情景。;-(

9. ES6中的類

如果你喜歡面向對象編程,那么你會特別喜歡這個特性。他讓你編寫和繼承類時就跟在Facebook上發一個評論這么簡單。

在ES5中,因為沒有class關鍵字(但它是毫無作用的保留字),類的創建和使用是讓人十分痛苦的事情。更慘的是,很多偽類的實現像pseude-classicalclassicalfunctional讓人越來越摸不着頭腦,為JavaScript的信仰戰爭火上澆油。

我不會給你展示在ES5中怎么去編寫一個類(是啦是啦從對象可以衍生出來其他的類和對象),因為有太多方法去完成。我們直接看ES6的示例,告訴你ES6的類會用prototype來實現而不是function。現在有一個baseModel類,其中我們可以定義構造函數和getName()方法。

注意到我給optionsdata用了默認參數,而且方法名再也不用加上function或者:了。還有一個很大的區別,你不能像構造函數里面一樣向this.Name指派值。怎么說呢,和函數有相同縮進的代碼里,你不能向name賦值。如果有這個需要的話,在構造函數里面完成。

使用NAME extends PARENT_NAME語法,AccountModelbaseModel繼承而來。

調用父類構造函數時,只需帶上參數輕松的調用super()方法。

想要高級一點的話,你可以像這樣弄一個getter方法,這樣accountsData就會變成一個屬性。

現在你要怎么用這個魔咒,很簡單,就跟讓三歲小孩相信聖誕老人存在一樣。

如果好奇輸出結果的話:

 

10. ES6中的模塊化

你可能知道,ES6之前JavaScript並沒有對模塊化有過原生的支持,人們想出來AMDRequireJSCommenJS等等,現在終於有importexport運算符來實現了。

ES5中你會用script標簽和IIFE(立即執行函數),或者是其他的像AMD之類的庫,但是ES6中你可以用export來暴露你的類。我是喜歡Node.js的人,所以我用和Node.js語法一樣的CommonJS,然后用Browserfy來瀏覽器化。現在我們有一個port變量和getAccounts方法,在ES5中:

在ES5的main.js中,用require('模塊')來導入:

但是在ES6中,我們用exportimport。比如這是ES6中的module.js文件:

在需要引入的main.js文件中,可以用import {名稱} from '模塊'語法:

或者就直接在main.js中引入所有的變量:

個人來說,我覺得這樣的模塊化有些搞不懂。確實,這樣會更傳神一些 。但是Node.js中的模塊不會馬上就改過來,瀏覽器和服務器的代碼最好是用同樣的標准,所以目前我還是會堅持CommonJS/Node.js的方式。

目前來說瀏覽器對ES6的支持還遙遙無期(本文寫作時),所以你需要一些像jspm這樣的工具來用ES6的模塊。

想要了解更多ES6中的模塊化和例子的話,來看這篇文章,不管怎么說,寫現代化的JavaScript吧!

怎么樣可以在今天就用上ES6(Babel)

ES6標准已經敲定,但還未被所有瀏覽器支持(Firefox的ES6功能一覽),如果想馬上就用上ES6,需要一個像Babel這樣的編譯器。你可以把他當獨立工具用,也可以將他集成到構建系統里,Babel對GulpGruntWebpack都有對應的插件

安裝Gulp插件示例:

gulpfile.js中,定義這么一個任務,將src目錄下的app.js文件編譯到build目錄下:

 

Node.js和ES6

對於Node.js,你可以用構建工具或者直接用獨立模塊babel-core

然后在Node.js中調用這個函數:

 

ES6的一些總結

ES6中還有很多你可能都用不上(至少現在用不上)的可圈可點的特性,以下無特定順序:

    1. Math / Number / String / Array / Object中新的方法
    2. 二進制和八進制數據類型
    3. 自動展開多余參數
    4. For of循環(又見面了CoffeeScript)
    5. Symbols
    6. 尾部調用優化
    7. generator
    8. 更新的數據結構(如MapSet


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM