ECMAScript 6簡介

ECMAScript 6(如下簡稱ES6)是JavaScript語言的下一代標準,已經在2015年6月正式發佈了。它的目標,是使得JavaScript語言能夠用來編寫複雜的大型應用程序,成爲企業級開發語言。javascript

標準的制定者有計劃,之後每一年發佈一次標準,使用年份做爲標準的版本。由於當前版本的ES6是在2015年發佈的,因此又稱ECMAScript 2015。也就是說,ES6就是ES2015,下一年應該會發布小幅修訂的ES2016。html

ECMAScript和JavaScript的關係

一個常見的問題是,ECMAScript和JavaScript究竟是什麼關係?java

要講清楚這個問題,須要回顧歷史。1996年11月,JavaScript的創造者Netscape公司,決定將JavaScript提交給國際標準化組織ECMA,但願這種語言可以成爲國際標準。次年,ECMA發佈262號標準文件(ECMA-262)的初版,規定了瀏覽器腳本語言的標準,並將這種語言稱爲ECMAScript,這個版本就是1.0版。node

該標準從一開始就是針對JavaScript語言制定的,可是之因此不叫JavaScript,有兩個緣由。一是商標,Java是Sun公司的商標,根據受權協議,只有Netscape公司能夠合法地使用JavaScript這個名字,且JavaScript自己也已經被Netscape公司註冊爲商標。二是想體現這門語言的制定者是ECMA,不是Netscape,這樣有利於保證這門語言的開放性和中立性。react

所以,ECMAScript和JavaScript的關係是,前者是後者的規格,後者是前者的一種實現(另外的ECMAScript方言還有Jscript和ActionScript)。在平常場合,這兩個詞是能夠互換的。git

ECMAScript的歷史

ES6從開始制定到最後發佈,整整用了15年。es6

前面提到,ECMAScript 1.0是1997年發佈的,接下來的兩年,連續發佈了ECMAScript 2.0(1998年6月)和ECMAScript 3.0(1999年12月)。3.0版是一個巨大的成功,在業界獲得普遍支持,成爲通行標準,奠基了JavaScript語言的基本語法,之後的版本徹底繼承。直到今天,初學者一開始學習JavaScript,其實就是在學3.0版的語法。github

2000年,ECMAScript 4.0開始醞釀。這個版本最後沒有經過,可是它的大部份內容被ES6繼承了。所以,ES6制定的起點實際上是2000年。npm

爲何ES4沒有經過呢?由於這個版本太激進了,對ES3作了完全升級,致使標準委員會的一些成員不肯意接受。ECMA的第39號技術專家委員會(Technical Committee 39,簡稱TC39)負責制訂ECMAScript標準,成員包括Microsoft、Mozilla、Google等大公司。json

2007年10月,ECMAScript 4.0版草案發布,原本預計次年8月發佈正式版本。可是,各方對因而否經過這個標準,發生了嚴重分歧。以Yahoo、Microsoft、Google爲首的大公司,反對JavaScript的大幅升級,主張小幅改動;以JavaScript創造者Brendan Eich爲首的Mozilla公司,則堅持當前的草案。

2008年7月,因爲對於下一個版本應該包括哪些功能,各方分歧太大,爭論過於激烈,ECMA開會決定,停止ECMAScript 4.0的開發,將其中涉及現有功能改善的一小部分,發佈爲ECMAScript 3.1,而將其餘激進的設想擴大範圍,放入之後的版本,因爲會議的氣氛,該版本的項目代號起名爲Harmony(和諧)。會後不久,ECMAScript 3.1就更名爲ECMAScript 5。

2009年12月,ECMAScript 5.0版正式發佈。Harmony項目則一分爲二,一些較爲可行的設想定名爲JavaScript.next繼續開發,後來演變成ECMAScript 6;一些不是很成熟的設想,則被視爲JavaScript.next.next,在更遠的未來再考慮推出。TC39委員會的整體考慮是,ES5與ES3基本保持兼容,較大的語法修正和新功能加入,將由JavaScript.next完成。當時,JavaScript.next指的是ES6,第六版發佈之後,就指ES7。TC39的判斷是,ES5會在2013年的年中成爲JavaScript開發的主流標準,並在此後五年中一直保持這個位置。

2011年6月,ECMAscript 5.1版發佈,而且成爲ISO國際標準(ISO/IEC 16262:2011)。

2013年3月,ECMAScript 6草案凍結,再也不添加新功能。新的功能設想將被放到ECMAScript 7。

2013年12月,ECMAScript 6草案發布。而後是12個月的討論期,聽取各方反饋。

2015年6月,ECMAScript 6正式經過,成爲國際標準。從2000年算起,這時已通過去了15年。

部署進度

各大瀏覽器的最新版本,對ES6的支持能夠查看kangax.github.io/es5-compat-table/es6/。隨着時間的推移,支持度已經愈來愈高了,ES6的大部分特性都實現了。

Node.js是JavaScript語言的服務器運行環境,對ES6的支持度比瀏覽器更高。經過Node,能夠體驗更多ES6的特性。建議使用版本管理工具nvm,來安裝Node,由於能夠自由切換版本。不過,nvm不支持Windows系統,若是你使用Windows系統,下面的操做能夠改用nvmwnvm-windows代替。

安裝nvm須要打開命令行窗口,運行下面的命令。

$ curl -o https://raw.githubusercontent.com/creationix/nvm/<version number>/install.sh | bash

上面命令的version number處,須要用版本號替換。本節寫做時的版本號是v0.29.0。該命令運行後,nvm會默認安裝在用戶主目錄的.nvm子目錄。

而後,激活nvm

$ source ~/.nvm/nvm.sh

激活之後,安裝Node的最新版。

$ nvm install node

安裝完成後,切換到該版本。

$ nvm use node

使用下面的命令,能夠查看Node全部已經實現的ES6特性。

$ node --v8-options | grep harmony  --harmony_typeof  --harmony_scoping  --harmony_modules  --harmony_symbols  --harmony_proxies  --harmony_collections  --harmony_observation  --harmony_generators  --harmony_iteration  --harmony_numeric_literals  --harmony_strings  --harmony_arrays  --harmony_maths  --harmony

上面命令的輸出結果,會由於版本的不一樣而有所不一樣。

我寫了一個ES-Checker模塊,用來檢查各類運行環境對ES6的支持狀況。訪問ruanyf.github.io/es-checker,能夠看到您的瀏覽器支持ES6的程度。運行下面的命令,能夠查看本機支持ES6的程度。

$ npm install -g es-checker
$ es-checker=========================================Passes 24 feature Dectations
Your runtime supports 57% of ECMAScript 6=========================================

Babel轉碼器

Babel是一個普遍使用的ES6轉碼器,能夠將ES6代碼轉爲ES5代碼,從而在瀏覽器或其餘環境執行。這意味着,你能夠用ES6的方式編寫程序,又不用擔憂現有環境是否支持。下面是一個例子。

// 轉碼前input.map(item => item + 1);// 轉碼後input.map(function (item) {
  return item + 1;});

上面的原始代碼用了箭頭函數,這個特性尚未獲得普遍支持,Babel將其轉爲普通函數,就能在現有的JavaScript環境執行了。

命令行環境

命令行下,Babel的安裝命令以下。

$ npm install --global babel-cli
$ npm install --save babel-preset-es2015

而後在當前目錄下,新建一個配置文件.babelrc

// .babelrc{
  "presets": ['es2015']}

Babel自帶一個babel-node命令,提供支持ES6的REPL環境。它支持Node的REPL環境的全部功能,並且能夠直接運行ES6代碼。

$ babel-node>> console.log([1,2,3].map(x => x * x))
    [ 1, 4, 9 ]>

babel-node命令也能夠直接運行ES6腳本。假定將上面的代碼放入腳本文件es6.js

$ babel-node es6.js[1, 4, 9]

babel命令能夠將ES6代碼轉爲ES5代碼。

$ babel es6.js"use strict";console.log([1, 2, 3].map(function (x) {
  return x * x;}));

-o參數將轉換後的代碼,從標準輸出導入文件。

$ babel es6.js -o es5.js# 或者$ babel es6.js --out-file es5.js

-d參數用於轉換整個目錄。

$ babel -d build-dir source-dir

注意,-d參數後面跟的是輸出目錄。

若是但願生成source map文件,則要加上-s參數。

$ babel -d build-dir source-dir -s

瀏覽器環境

Babel也能夠用於瀏覽器。可是,從Babel 6.0開始,再也不直接提供瀏覽器版本,而是要用構建工具構建出來。若是你沒有或不想使用構建工具,只有經過安裝5.x版本的babel-core模塊獲取。

$ npm install babel-core@5

運行上面的命令之後,就能夠在當前目錄的node_modules/babel-core/子目錄裏面,找到babel的瀏覽器版本browser.js(未精簡)和browser.min.js(已精簡)。

而後,將下面的代碼插入網頁。

<script src="node_modules/babel-core/browser.js"></script>
<script type="text/babel">
// Your ES6 code
</script>

上面代碼中,browser.js是Babel提供的轉換器腳本,能夠在瀏覽器運行。用戶的ES6腳本放在script標籤之中,可是要註明type="text/babel"

這種寫法是實時將ES6代碼轉爲ES5,對網頁性能會有影響。生產環境須要加載已經轉碼完成的腳本。

下面是Babel配合Browserify一塊兒使用,能夠生成瀏覽器可以直接加載的腳本。首先,安裝babelify模塊。

$ npm install --save-dev babelify babel-preset-es2015

而後,再用命令行轉換ES6腳本。

$  browserify script.js -o bundle.js \  -t [ babelify --presets [ es2015 react ] ]

上面代碼將ES6腳本script.js,轉爲bundle.js,瀏覽器直接加載後者就能夠了。

package.json設置下面的代碼,就不用每次命令行都輸入參數了。

{
  "browserify": {
    "transform": [["babelify", { "presets": ["es2015"] }]]
  }}

Node環境

Node腳本之中,須要轉換ES6腳本,能夠像下面這樣寫。

先安裝babel-corebabel-preset-es2015

$ npm install --save-dev babel-core babel-preset-es2015

而後,在項目根目錄下新建一個.babelrc文件。

{
  "presets": ["es2015"]}

而後在腳本中,調用babel-coretransform方法。

var es5Code = 'let x = n => n + 1';var es6Code = require('babel-core')
  .transform(es5Code, {presets: ['es2015']})
  .code;// '"use strict";\n\nvar x = function x(n) {\n  return n + 1;\n};'

上面代碼中,transform方法的第一個參數是一個字符串,表示須要轉換的ES5代碼,第二個參數是轉換的配置對象。

Node腳本還有一種特殊的babel用法,即把babel加載爲require命令的一個鉤子。安裝babel-corebabel-preset-es2015之後,先在項目的根目錄下面,設置一個配置文件.babelrc

// .babelrc{
  "presets": ["es2015"]}

而後,在你的應用的入口腳本(entry script)頭部,加入下面的語句。

require("babel-core/register");

有了上面這行語句,後面全部經過require命令加載的後綴名爲.es6.es.jsx.js的腳本,都會先經過babel轉碼後再加載。

須要注意的是,Babel默認不會轉換Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局對象,以及一些定義在全局對象上的方法(好比Object.assign)。若是你用到了這些功能,當前的運行環境又不支持。就須要安裝babel-polyfill模塊。

$ npm install babel-polyfill --save

而後,在全部腳本頭部加上一行。

require('babel-polyfill');// 或者import 'babel-polyfill';

在線轉換

Babel提供一個REPL在線編譯器,能夠在線將ES6代碼轉爲ES5代碼。轉換後的代碼,能夠直接做爲ES5代碼插入網頁運行

Traceur轉碼器

Google公司的Traceur轉碼器,也能夠將ES6代碼轉爲ES5代碼。

直接插入網頁

Traceur容許將ES6代碼直接插入網頁。首先,必須在網頁頭部加載Traceur庫文件。

<!-- 加載Traceur編譯器 --><script src="http://google.github.io/traceur-compiler/bin/traceur.js"
        type="text/javascript"></script><!-- 將Traceur編譯器用於網頁 --><script src="http://google.github.io/traceur-compiler/src/bootstrap.js"
        type="text/javascript"></script><!-- 打開實驗選項,不然有些特性可能編譯不成功 --><script>
        traceur.options.experimental = true;</script>

接下來,就能夠把ES6代碼放入上面這些代碼的下方。

<script type="module">
  class Calc {
    constructor(){
      console.log('Calc constructor');
    }
    add(a, b){
      return a + b;
    }
  }

  var c = new Calc();
  console.log(c.add(4,5));</script>

正常狀況下,上面代碼會在控制檯打印出9。

注意,script標籤的type屬性的值是module,而不是text/javascript。這是Traceur編譯器識別ES6代碼的標識,編譯器會自動將全部type=module的代碼編譯爲ES5,而後再交給瀏覽器執行。

若是ES6代碼是一個外部文件,也能夠用script標籤插入網頁。

<script type="module" src="calc.js" ></script>

在線轉換

Traceur也提供一個在線編譯器,能夠在線將ES6代碼轉爲ES5代碼。轉換後的代碼,能夠直接做爲ES5代碼插入網頁運行。

上面的例子轉爲ES5代碼運行,就是下面這個樣子。

<script src="http://google.github.io/traceur-compiler/bin/traceur.js"
        type="text/javascript"></script><script src="http://google.github.io/traceur-compiler/src/bootstrap.js"
        type="text/javascript"></script><script>
        traceur.options.experimental = true;</script><script>$traceurRuntime.ModuleStore.getAnonymousModule(function() {
  "use strict";

  var Calc = function Calc() {
    console.log('Calc constructor');
  };

  ($traceurRuntime.createClass)(Calc, {add: function(a, b) {
    return a + b;
  }}, {});

  var c = new Calc();
  console.log(c.add(4, 5));
  return {};});</script>

命令行轉換

做爲命令行工具使用時,Traceur是一個Node.js的模塊,首先須要用npm安裝。

$ npm install -g traceur

安裝成功後,就能夠在命令行下使用traceur了。

traceur直接運行es6腳本文件,會在標準輸出顯示運行結果,之前面的calc.js爲例。

$ traceur calc.js
Calc constructor9

若是要將ES6腳本轉爲ES5保存,要採用下面的寫法

$ traceur --script calc.es6.js --out calc.es5.js

上面代碼的--script選項表示指定輸入文件,--out選項表示指定輸出文件。

爲了防止有些特性編譯不成功,最好加上--experimental選項。

$ traceur --script calc.es6.js --out calc.es5.js --experimental

命令行下轉換的文件,就能夠放到瀏覽器中運行。

Node.js環境的用法

Traceur的Node.js用法以下(假定已安裝traceur模塊)。

var traceur = require('traceur');var fs = require('fs');// 將ES6腳本轉爲字符串var contents = fs.readFileSync('es6-file.js').toString();var result = traceur.compile(contents, {
  filename: 'es6-file.js',
  sourceMap: true,
  // 其餘設置  modules: 'commonjs'});if (result.error)
  throw result.error;// result對象的js屬性就是轉換後的ES5代碼fs.writeFileSync('out.js', result.js);// sourceMap屬性對應map文件fs.writeFileSync('out.js.map', result.sourceMap);

ECMAScript 7

2013年3月,ES6的草案封閉,再也不接受新功能了。新的功能將被加入ES7。

任何人均可以向TC39提案,從提案到變成正式標準,須要經歷五個階段。每一個階段的變更都須要由TC39委員會批准。

  • Stage 0 - Strawman(展現階段)

  • Stage 1 - Proposal(徵求意見階段)

  • Stage 2 - Draft(草案階段)

  • Stage 3 - Candidate(候選人階段)

  • Stage 4 - Finished(定案階段)

一個提案只要能進入Stage 2,就差很少等於確定會包括在ES7裏面。

本書的寫做目標之一,是跟蹤ECMAScript語言的最新進展。對於那些明確的、或者頗有但願列入ES7的功能,尤爲是那些Babel已經支持的功能,都將予以介紹。

本書介紹的ES7功能清單以下。

Stage 0

  • es7.comprehensions:數組推導

  • es7.classProperties:類的屬性

  • es7.functionBind:函數的綁定運算符

Stage 1

  • es7.decorators:修飾器

  • es7.exportExtensions:export的擴展寫法

  • es7.trailingFunctionCommas:函數參數的尾逗號

Stage 2

  • es7.exponentiationOperator:指數運算符

  • es7.asyncFunctions:async函數

  • es7.objectRestSpread:對象的Rest參數和擴展運算符

ECMAScript當前的全部提案,能夠在TC39的官方網站Github.com/tc39/ecma262查看。

Babel轉碼器能夠經過安裝和使用插件來使用各個stage的語法。

相關文章
相關標籤/搜索