最近在InfoQ 中看到一篇文章 成為一名優秀的Web前端開發者,裡面提到學習 ECMAScript 2015 這一個部份,又因為在 github 看到越來越多 Javascript 專案始用 ES6

Javascript這個語言,是有「標準規格」的,叫做ECMA-262,這個標準規格,是由ECMA International (European Computer Manufacturers Association International)這個標準組織所制定,所以也稱呼它為ECMAScript。這個規格涵蓋了所有Javascript的核心,是各種Javascript執行環境一定會有的東西。在此之上,瀏覽器內就會額外加入DOM等擴充,而像node.js這樣的伺服器端環境,也有他自己的擴充,不過核心的部份是大家都一樣的。(附帶一提,C#的標準規格也是ECMA制定的) 初探 ES6(1)Harmony 的黑歷史 by fillano | CodeData

2015 年的 ECMAScript 是一個顯著的更新。上一次版本 ES5 的標準是在 2009 年訂定的,AngularJS, Aurelia, ReactJS, Ionic 都是架構在 ES5 的基礎上, 不過 ReactJS 也開始支援了 ES6,身為一個前端的工程師也是時候開始學習了

ECMAScript 2015 (ES6)

ES6 包含了很多的新特性,更詳細的說明請參照 Reference - ES6,本次的 Simple 只用到幾個 ES6 最基本用法

  • arrow
  • classes
  • enhanced object literals
  • template strings
  • destructuring
  • default + rest + spread
  • let + const
  • iterators + for..of
  • generators
  • unicode
  • modules
  • module loaders
  • map + set + weakmap + weakset
  • proxies
  • symbols
  • subclassable built-ins
  • promises
  • math + number + string + object APIs
  • binary and octal literals
  • reflect api
  • tail calls

Setting Started

1
2
3
4
5
6
7
8
9
10
11
# clone webpack-es6 repo
$ git clone https://github.com/cage1016/webpack-es6-demo
# install node package
$ npm install
# complie js
$ npm run watch
# open index.html
$ open -a 'Google Chrome' index.html

webpack

目前 Browser 還沒有全面支援 ES6,所以在使用時候就必需進行轉譯,這邊我們使用的是 shama/es6-loader 的轉譯器

webpack.config.js

進行 webpack.config.js 檔案的配置:

  1. 設置 webpack 進入點. ./app/entry.js
  2. 設置轉譯後檔案 bundle.js (最後需要在 index.html 中引用 bundle.js)
  3. 設置 babel-loader 模組來進行 ES6 的轉譯
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './app/entry.js',
output: {
path: __dirname,
filename: 'bundle.js',
},
module: {
loaders: [{
test: path.join(__dirname, 'app'),
loader: 'babel-loader',
exclude: /node_modules/,
}, ],
},
plugins: [
// Avoid publishing files when compilation failed
new webpack.NoErrorsPlugin(),
],
stats: {
// Nice colored output
colors: true,
},
// Create Sourcemaps for the bundle
devtool: 'source-map',
};

Polygon

app/Polygon.js

app/Polygon.js 中使用到了 ES6 中三個新的特性:

  1. classes/inheritance/static
  2. module
  3. arrow
  4. strings
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Polygon {
constructor(points) {
this.points = points;
}
getArea() {
let area = 0;
let j = this.points.length - 1;
for (let i = 0; i < this.points.length; i++) {
area = area +
(this.points[j][0] + this.points[i][0]) *
(this.points[j][1] - this.points[i][1]);
j = i;
}
return Math.abs(area / 2);
}
getPoints() {
return this.points.map(n => `(${n[0]},${n[1]})`).join(',');
}
toString() {
return `I am ${this.name}, area = ${this.getArea()}`
}
}
class Rectangle extends Polygon {
constructor(points) {
super(points, 'Rectanger');
this.name = 'Rectanger'
}
}
class Triangle extends Polygon {
constructor(points) {
super(points, 'Triangle');
this.name = 'Triangle';
}
static create(points) {
return new Triangle(points);
}
}
export {
Triangle, Polygon, Rectangle
}

Entry

app/entry.js

app/entry.js 中使用到了 ES6 中新的特性:

  1. module 引用的方式
  2. let (類似 ES5 中的 var,不過 let 會把 scope 區隔開來)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import {
Rectangle, Triangle
}
from './Polygon';
let r = new Rectangle([
[4, 4],
[4, -4],
[-4, -4],
[-4, 4],
]);
let t = Triangle.create([
[4, 6],
[4, -4],
[8, -4],
])
let body = document.querySelector('body');
body.innerHTML = [
r.toString(),
r.getPoints(),
t.toString(),
t.getPoints(),
].join('<br/>');

最後在 Browser 中看到三結果

1
2
3
4
I am Rectanger, area = 64
(4,4),(4,-4),(-4,-4),(-4,4)
I am Triangle, area = 20
(4,6),(4,-4),(8,-4)

Reference

ES6

webpack