鍍金池/ 教程/ HTML/ ECMAScript 6簡介
數(shù)組的擴展
Class和Module
Set 和 Map 數(shù)據(jù)結(jié)構(gòu)
異步操作
對象的擴展
Generator 函數(shù)
數(shù)值的擴展
變量的解構(gòu)賦值
Iterator 和 for...of 循環(huán)
Promise 對象
參考鏈接
ECMAScript 6簡介
作者簡介
字符串的擴展
編程風(fēng)格
let 和 const 命令
函數(shù)的擴展

ECMAScript 6簡介

ECMAScript 6(以下簡稱 ES6)是 JavaScript 語言的下一代標(biāo)準(zhǔn),已經(jīng)在 2015 年 6 月正式發(fā)布了。Mozilla 公司將在這個標(biāo)準(zhǔn)的基礎(chǔ)上,推出 JavaScript 2.0。

ES6 的目標(biāo),是使得 JavaScript 語言可以用來編寫大型的復(fù)雜的應(yīng)用程序,成為企業(yè)級開發(fā)語言。

ECMAScript 和 JavaScript 的關(guān)系

很多初學(xué)者會感到困惑:ECMAScript 和 JavaScript 到底是什么關(guān)系?簡單說,ECMAScript 是 JavaScript 語言的國際標(biāo)準(zhǔn),JavaScript 是 ECMAScript 的實現(xiàn)。

要講清楚這個問題,需要回顧歷史。1996 年 11 月,JavaScript 的創(chuàng)造者 Netscape 公司,決定將 JavaScript 提交給國際標(biāo)準(zhǔn)化組織 ECMA,希望這種語言能夠成為國際標(biāo)準(zhǔn)。次年,ECMA 發(fā)布 262 號標(biāo)準(zhǔn)文件(ECMA-262)的第一版,規(guī)定了瀏覽器腳本語言的標(biāo)準(zhǔn),并將這種語言稱為 ECMAScript。這個版本就是 ECMAScript 1.0 版。

之所以不叫 JavaScript,有兩個原因。一是商標(biāo),Java 是 Sun 公司的商標(biāo),根據(jù)授權(quán)協(xié)議,只有 Netscape 公司可以合法地使用 JavaScript 這個名字,且 JavaScript 本身也已經(jīng)被 Netscape 公司注冊為商標(biāo)。二是想體現(xiàn)這門語言的制定者是 ECMA,不是 Netscape,這樣有利于保證這門語言的開放性和中立性。因此,ECMAScript 和 JavaScript 的關(guān)系是,前者是后者的規(guī)格,后者是前者的一種實現(xiàn)。在日常場合,這兩個詞是可以互換的。

ECMAScript 的歷史

1998 年 6 月,ECMAScript 2.0 版發(fā)布。

1999 年 12 月,ECMAScript 3.0 版發(fā)布,成為 JavaScript 的通行標(biāo)準(zhǔn),得到了廣泛支持。

2007 年 10 月,ECMAScript 4.0 版草案發(fā)布,對 3.0 版做了大幅升級,預(yù)計次年 8 月發(fā)布正式版本。草案發(fā)布后,由于 4.0 版的目標(biāo)過于激進,各方對于是否通過這個標(biāo)準(zhǔn),發(fā)生了嚴(yán)重分歧。以 Yahoo、Microsoft、Google 為首的大公司,反對 JavaScript 的大幅升級,主張小幅改動;以 JavaScript 創(chuàng)造者 Brendan Eich 為首的 Mozilla 公司,則堅持當(dāng)前的草案。

2008 年 7 月,由于對于下一個版本應(yīng)該包括哪些功能,各方分歧太大,爭論過于激進,ECMA 開會決定,中止 ECMAScript 4.0 的開發(fā),將其中涉及現(xiàn)有功能改善的一小部分,發(fā)布為 ECMAScript 3.1,而將其他激進的設(shè)想擴大范圍,放入以后的版本,由于會議的氣氛,該版本的項目代號起名為 Harmony(和諧)。會后不久,ECMAScript 3.1 就改名為 ECMAScript 5。

2009 年 12 月,ECMAScript 5.0 版正式發(fā)布。Harmony 項目則一分為二,一些較為可行的設(shè)想定名為 JavaScript.next 繼續(xù)開發(fā),后來演變成 ECMAScript 6;一些不是很成熟的設(shè)想,則被視為 JavaScript.next.next,在更遠的將來再考慮推出。

2011 年 6 月,ECMAscript 5.1 版發(fā)布,并且成為 ISO 國際標(biāo)準(zhǔn)(ISO/IEC 16262:2011)。

2013 年 3 月,ECMAScript 6 草案凍結(jié),不再添加新功能。新的功能設(shè)想將被放到 ECMAScript 7。

2013 年 12 月,ECMAScript 6 草案發(fā)布。然后是 12 個月的討論期,聽取各方反饋。

2015 年6 月,ECMAScript 6 正式通過,成為國際標(biāo)準(zhǔn)。

ECMA 的第 39 號技術(shù)專家委員會(Technical Committee 39,簡稱 TC39)負(fù)責(zé)制訂 ECMAScript 標(biāo)準(zhǔn),成員包括 Microsoft、Mozilla、Google 等大公司。TC39 的總體考慮是,ES5 與 ES3 基本保持兼容,較大的語法修正和新功能加入,將由 JavaScript.next 完成。當(dāng)時,JavaScript.next 指的是 ES6,第六版發(fā)布以后,就指 ES7。TC39 的判斷是,ES5 會在 2013 年的年中成為 JavaScript 開發(fā)的主流標(biāo)準(zhǔn),并在此后五年中一直保持這個位置。

部署進度

各大瀏覽器的最新版本,對 ES6 的支持可以查看kangax.github.io/es5-compat-table/es6/。隨著時間的推移,支持度已經(jīng)越來越高了,ES6 的大部分特性都實現(xiàn)了。

Node.js 和 io.js(一個部署新功能更快的 Node 分支)對 ES6 的支持度,比瀏覽器更高。通過它們,可以體驗更多 ES6 的特性。建議使用版本管理工具nvm,來安裝 Node.js 和 io.js。不過,nvm 不支持 Windows 系統(tǒng),下面的操作可以改用nvmwnvm-windows代替。

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

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

上面命令的 version number 處,需要用版本號替換。本書寫作時的版本號是 v0.25.4。

該命令運行后,nvm 會默認(rèn)安裝在用戶主目錄的 .nvm 子目錄。然后,激活 nvm。

$ source ~/.nvm/nvm.sh

激活以后,安裝 Node 或 io.js 的最新版。

$ nvm install node
# 或
$ nvm install iojs

安裝完成后,就可以在各種版本的 node 之間自由切換。

# 切換到node
$ nvm use node

# 切換到iojs
$ nvm use iojs

需要注意的是,Node.js 對 ES6 的支持,需要打開 harmony 參數(shù),io.js 不需要。

$ node --harmony
# io.js不需要打開harmony參數(shù)
$ node

上面命令執(zhí)行后,就會進入 REPL 環(huán)境,該環(huán)境支持所有已經(jīng)實現(xiàn)的 ES6 特性。

使用下面的命令,可以查看 Node.js 所有已經(jīng)實現(xiàn)的 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

上面命令的輸出結(jié)果,會因為版本的不同而有所不同。

Babel 轉(zhuǎn)碼器

Babel是一個廣泛使用的 ES6 轉(zhuǎn)碼器,可以 ES6 代碼轉(zhuǎn)為 ES5 代碼,從而在瀏覽器或其他環(huán)境執(zhí)行。這意味著,你可以用 ES6 的方式編寫程序,又不用擔(dān)心現(xiàn)有環(huán)境是否支持。它的安裝命令如下。

$ npm install --global babel

Babel 自帶一個babel-node命令,提供支持 ES6 的 REPL 環(huán)境。它支持 Node 的 REPL 環(huán)境的所有功能,而且可以直接運行 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 代碼轉(zhuǎn)為 ES5 代碼。

$ babel es6.js
"use strict";

console.log([1, 2, 3].map(function (x) {
  return x * x;
}));

-o 參數(shù)將轉(zhuǎn)換后的代碼,從標(biāo)準(zhǔn)輸出導(dǎo)入文件。

$ babel es6.js -o es5.js

Babel 也可以用于瀏覽器。

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

上面代碼中,browser.js是 Babel 提供的轉(zhuǎn)換器腳本,可以在瀏覽器運行。用戶的 ES6 腳本放在 script 標(biāo)簽之中,但是要注明type="text/babel"。

Traceur 轉(zhuǎn)碼器

Google 公司的Traceur轉(zhuǎn)碼器,也可以將 ES6 代碼轉(zhuǎn)為 ES5 代碼。

直接插入網(wǎng)頁

Traceur 允許將 ES6 代碼直接插入網(wǎng)頁。首先,必須在網(wǎng)頁頭部加載 Traceur 庫文件。

<!-- 加載Traceur編譯器 -->
<script src="http://google.github.io/traceur-compiler/bin/traceur.js"
        type="text/javascript"></script>
<!-- 將Traceur編譯器用于網(wǎng)頁 -->
<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 標(biāo)簽的 type 屬性的值是 module,而不是 text/javascript。這是 Traceur 編譯器識別 ES6 代碼的標(biāo)識,編譯器會自動將所有 type=module 的代碼編譯為 ES5,然后再交給瀏覽器執(zhí)行。

如果 ES6 代碼是一個外部文件,也可以用script標(biāo)簽插入網(wǎng)頁。

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

在線轉(zhuǎn)換

Traceur 提供一個在線編譯器,可以在線將 ES6 代碼轉(zhuǎn)為 ES5 代碼。轉(zhuǎn)換后的代碼,可以直接作為 ES5 代碼插入網(wǎng)頁運行。

上面的例子轉(zhuǎn)為 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>

命令行轉(zhuǎn)換

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

$ npm install -g traceur

安裝成功后,就可以在命令行下使用 traceur 了。

traceur 直接運行 es6 腳本文件,會在標(biāo)準(zhǔn)輸出顯示運行結(jié)果,以前面的 calc.js 為例。

$ traceur calc.js
Calc constructor
9

如果要將 ES6 腳本轉(zhuǎn)為 ES5 保存,要采用下面的寫法

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

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

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

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

命令行下轉(zhuǎn)換的文件,就可以放到瀏覽器中運行。

Node.js 環(huán)境的用法

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

var traceur = require('traceur');
var fs = require('fs');

// 將ES6腳本轉(zhuǎn)為字符串
var contents = fs.readFileSync('es6-file.js').toString();

var result = traceur.compile(contents, {
  filename: 'es6-file.js',
  sourceMap: true,
  // 其他設(shè)置
  modules: 'commonjs'
});

if (result.error)
  throw result.error;

// result對象的js屬性就是轉(zhuǎn)換后的ES5代碼
fs.writeFileSync('out.js', result.js);
// sourceMap屬性對應(yīng)map文件
fs.writeFileSync('out.js.map', result.sourceMap);

ECMAScript 7

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

ES7 可能包括的功能有:

(1)Object.observe:用來監(jiān)聽對象(以及數(shù)組)的變化。一旦監(jiān)聽對象發(fā)生變化,就會觸發(fā)回調(diào)函數(shù)。

(2)Async函數(shù):在 Promise 和 Generator 函數(shù)基礎(chǔ)上,提出的異步操作解決方案。

(3)Multi-Threading:多線程支持。目前,Intel 和 Mozilla 有一個共同的研究項目 RiverTrail,致力于讓 JavaScript 多線程運行。預(yù)計這個項目的研究成果會被納入 ECMAScript 標(biāo)準(zhǔn)。

(4)Traits:它將是“類”功能(class)的一個替代。通過它,不同的對象可以分享同樣的特性。

其他可能包括的功能還有:更精確的數(shù)值計算、改善的內(nèi)存回收、增強的跨站點安全、類型化的更貼近硬件的低級別操作、國際化支持(Internationalization Support)、更多的數(shù)據(jù)結(jié)構(gòu)等等。