<style>
.reveal, .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 {
font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, "Microsoft JhengHei", Meiryo, "MS ゴシック", "MS Gothic", sans-serif;
}
h1, h2, h3, h4, h5, h6 {
text-transform: none !important;
}
.js-img {
background: url(https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/JavaScript-logo.png/480px-JavaScript-logo.png) center/contain;
width: 350px;
height: 350px;
display: block;
margin: 20px auto !important;
border: 4px solid white !important;
}
</style>
# ECMAScript 6 簡介
###### ECMAScript (ES) 6 = ECMAScript 2015
Cheng-Han Wu<br />[@jackymaxj](https://twitter.com/jackymaxj)
**參考自**
[Introduction to ECMAScript 6](http://coenraets.org/present/es6)
Christophe Coenraets<br/>[@ccoenraets](https://twitter.com/ccoenraets)
---
<img src="https://avatars2.githubusercontent.com/u/2639151?v=3&s=460" style="width:150px;height:150px;border-radius:50%"/>
Cheng-Han Wu
Taipei, Taiwan
@jackymaxj
https://hackmd.io
https://github.com/jackycute
---
## 大綱
- Status 發展現況
- Variables & Constants 變數與常數
- Destructuring 解構
- Arrow Functions 箭號函數
- Promises
- Modules 模組
- Classes 類別
- Template Strings 樣板字串
- Generators
- Collections 集合
---
<div class="js-img"></div>
# 發展現況
----
## 專有名詞
- *JavaScript:* 語言的名稱
- *ECMAScript:* 語言的標準
- *TC 39:* 技術委員會
- *ECMAScript Harmony:* ES 5 後期改善
- *ECMAScript.Next:* 下一版本的代號
- *ECMAScript 6:* 下一版本的最終名稱
----
## 歷史演進
- *ECMAScript 1:* 1997
- *ECMAScript 2:* 1998
- *ECMAScript 3:* 1999
- *ECMAScript 4:* 拋棄
- *ECMAScript 5:* 2009
- *ECMAScript 6:* ?
----
## ECMAScript 6 目標
### 為了更好的支援:
- Complex Apps 複雜的應用程式
- Libraries 函式庫
- Code Generators 程式碼產生器
----
### 避免程式核心功能的各種不一致與分散性
Modules 模組, Promises, Classes 類別, 等等
----
## 向下相容性
> “不能讓網頁壞掉”
也就是說不能亂改 var 功能
----
## 什麼時候可以用?
- 相容性表格
請見:https://kangax.github.io/compat-table/es6
- 關注 [@esdiscuss](https://twitter.com/esdiscuss)
----
## 今天就開始用 ES6
轉譯器
- Babel
http://babeljs.io
- Traceur
https://github.com/google/traceur-compiler
- TypeScript
<small>(JavaScript 的延伸,同時也致力於符合 ECMAScript 6)</small>
http://www.typescriptlang.org
---
<div class="js-img"></div>
# 變數與常數
----
## var
函數內有效
```javascript=
function divide(x, y) {
if (y !== 0) {
var result;
result = x / y;
}
return result;
}
console.log(divide(10, 2)); // 5
```
----
## let
區塊內有效
```javascript=
function divide(x, y) {
if (y !== 0) {
let result;
result = x / y;
}
return result; // throws Error
}
console.log(divide(10, 2));
```
----
### const
區塊內有效
```javascript=
const PI = 3.14159265359;
const COLOR = {
name: "Red",
hexValue: "#FF0000"
};
```
不能重新給值或是重新定義
----
## 從變數建立物件
ECMAScript 5
```javascript=
var firstName = "Christophe";
var lastName = "Coenraets";
var twitterId = "@ccoenraets";
var speaker = {
firstName: firstName,
lastName: lastName,
twitterId: twitterId
};
```
----
## 從物件建立變數
ES6 Object Literals 物件字面
```javascript=
let firstName = "Christophe";
let lastName = "Coenraets";
let twitterId = "@ccoenraets";
let speaker = {firstName, lastName, twitterId};
```
<small>用 var 也可以</small>
---
<div class="js-img"></div>
# 解構
使用語法來對應陣列或是物件結構的字面
進而從中抽離資料
----
## 從陣列元素中建立變數
ECMAScript 5
```javascript=
var colors = ["red", "green", "blue"];
var primary = colors[0];
var secondary = colors[1];
var tertiary = colors[2];
console.log(primary); // red
console.log(secondary); // green
console.log(tertiary); // blue
```
----
## Spread Operator 分散運算子
```javascript=
var colors = ["red", "green", "blue", "yellow", "orange"];
var [primary, secondary, ...otherColors] = colors;
console.log(primary); // red
console.log(secondary); // green
console.log(otherColors); // [ 'blue', 'yellow', 'orange']
```
----
## 多回傳值的函數
```javascript=
function getDate() {
var d = new Date();
return [d.getDate(), d.getMonth() + 1, d.getFullYear()];
}
var [day, month, year] = getDate();
console.log(day); // 4
console.log(month); // 5
console.log(year); // 2015
```
----
## 從物件屬性建立變數
ECMAScript 5
```javascript=
var speaker = { firstName: "Christophe",
lastName: "Coenraets",
twitterId: "@ccoenraets" };
var firstName = speaker.firstName;
var lastName = speaker.lastName;
var twitterId = speaker.twitterId;
console.log(firstName); // Christophe
console.log(lastName); // Coenraets
console.log(twitterId); // @ccoenraets
```
----
## 從物件屬性建立變數
ES6 Object Destructuring 物件解構
```javascript=
var speaker = { firstName: "Christophe",
lastName: "Coenraets",
twitterId: "@ccoenraets" };
var {firstName, lastName, twitterId} = speaker;
console.log(firstName); // Christophe
console.log(lastName); // Coenraets
console.log(twitterId); // @ccoenraets
```
```javascript=
var {fName: firstName, lName: lastName, twId:twitterId} = speaker;
console.log(fName); // Christophe
```
---
<div class="js-img"></div>
# Arrow Functions<br>箭號函數
----
ES5 Function
```javascript=
var greeting = function(message, name) {
return message + ' ' + name;
}
console.log(greeting('Hello', 'Christophe'));
```
ES6 Arrow Function
<!-- .element: class="fragment" data-fragment-index="2" -->
```javascript=
var greeting = (message, name) => {
return message + ' ' + name;
}
```
<!-- .element: class="fragment" data-fragment-index="2" -->
```javascript=
var greeting = (message, name) => message + ' ' + name;
```
<!-- .element: class="fragment" data-fragment-index="3" -->
```javascript=
var greeting = name => 'Hello ' + name;
```
<!-- .element: class="fragment" data-fragment-index="4" -->
----
再一個範例
```javascript=
var array = [1, 2, 3];
var total = 0;
array.forEach(function(item) {
total = total + item;
});
console.log(total);
```
```javascript=
var array = [1, 2, 3];
var total = 0;
array.forEach(item => total = total + item);
console.log(total);
```
<!-- .element: class="fragment" data-fragment-index="1" -->
----
ECMAScript 5
> “var self = this” 也就是 “var that = this”
```javascript=
var obj = {
init: function () {
var self = this;
setTimeout(function() {
self.doSomething();
}, 1000);
},
doSomething: function() {
console.log("doing something in ES5");
}
};
obj.init();
```
----
ES 6 Arrow Functions
真正的 “this”
```javascript=
var obj = {
init: function() {
setTimeout(() => this.doSomething(), 1000);
},
doSomething: function() {
console.log("doing something in ES6");
}
};
obj.init();
```
----
Default Params 預設參數
```javascript=
var greeting = (name, msg="Hello") => msg + ' ' + name;
console.log(greeting('Christophe', 'Hi')); // Hi Christophe
console.log(greeting('Christophe')); // Hello Christophe
```
"function" 也可以用:
<!-- .element: class="fragment" data-fragment-index="1" -->
```javascript=
function greeting(name, message="Hello") {
return message + ' ' + name;
}
```
<!-- .element: class="fragment" data-fragment-index="2" -->
---
<div class="js-img"></div>
# Promises
----
## 地獄回傳金字塔
```javascript=
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// Do something with value4
});
});
});
});
```
<small>https://github.com/kriskowal/q</small>
----
## 回傳的問題
1. 難以組成 (循序或是同步)
2. 難以處理錯誤
3. 不合理的輸入參數與回傳值的語意
----
# Promise
尚未可用的值之代理者
1. 非同步函數回傳 promise
2. 呼叫者帶著 event handler 回傳 promise
3. 當 Event handler 有結果的時候處理它
➝ 清楚的輸入參數與回傳值的語意
----
## q Promises
定義
```javascript=
function step1() {
var deferred = Q.defer();
FS.readFile("foo.txt", "utf-8", function (error, text) {
if (error) {
deferred.reject(new Error(error));
} else {
deferred.resolve(text);
}
});
return deferred.promise;
}
```
----
## q Promises
使用
```javascript=
Q.fcall(step1)
.then(step2)
.then(step3)
.then(step4)
.then(function(value4) {
// Do something with value4
})
.catch(function(error) {
// Handle any error from all above steps
})
.done();
```
<small>
請把 *then(handler)* 想成 *addEventListener("done", handler)*
</small>
----
## jQuery Promises
定義
```javascript=
function getList() {
var deferred = $.Deferred();
if (list) {
deferred.resolve(list);
} else {
deferred.reject("no list");
}
return deferred.promise();
}
```
使用
<!-- .element: class="fragment" data-fragment-index="1" -->
```javascript=
service.getList()
.done(function(list) {
console.log(list);
})
.fail(function(error) {
console.log(error);
});
```
<!-- .element: class="fragment" data-fragment-index="1" -->
----
## ECMAScript 6 Promises
定義
```javascript=
function timeout(millis) {
var promise = new Promise(function (resolve, reject) {
setTimeout(function() {
resolve();
}, millis);
});
return promise;
}
```
使用
<!-- .element: class="fragment" data-fragment-index="1" -->
```javascript=
timeout(1000).then(function() {
console.log('done waiting');
});
```
<!-- .element: class="fragment" data-fragment-index="1" -->
Promisified setTimeout()
<!-- .element: class="fragment" data-fragment-index="2" -->
----
## ECMAScript 6 Promises
定義 假資料服務 (Service)
```javascript=
var employees;
function findAll() {
return new Promise(function (resolve, reject) {
if (employees) {
resolve(employees);
} else {
reject("employees is not defined");
}
});
}
```
----
## ECMAScript 6 Promises
使用 假資料服務 (Service)
```javascript=
findAll()
.then(function(employees) {
console.log(employees);
})
.catch(function(error) {
console.log(error);
});
```
---
<div class="js-img"></div>
# 模組
----
## AMD 模組
```javascript=
define(function (require) {
var $ = require('jquery');
var findAll = function() {
// implementation
};
var findById = function(id) {
// implementation
};
return {
findAll: findAll,
findById: findById
};
});
```
----
Common.js 模組
```javascript=
var findAll = function () {
// implementation
};
var findById = function(id) {
// implementation
};
module.exports = {
findAll: findAll,
findById: findById
};
```
----
## ECMAScript 6 模組
定義
```javascript=
// datelib.js
export const today = new Date();
export var shortDate = function() {
return today.getMonth() + 1 + '/' +
today.getDate() + '/' +
today.getFullYear();
}
```
使用
<!-- .element: class="fragment" data-fragment-index="1" -->
```javascript=
import {today, shortDate} from './datelib';
console.log(today); // Mon May 4 2015 11:04:06...
console.log(shortDate()); // 5/4/2015
import * as date from "./datelib";
console.log(date.today);
console.log(date.shortDate());
```
<!-- .element: class="fragment" data-fragment-index="1" -->
----
## ECMAScript 6 模組
定義 假資料 (Service)
```javascript=
export function findAll() {
// implementation
}
export function findById(id) {
// implementation
}
export var endpoint = "http://localhost:5000";
```
使用 假資料 (Service)
<!-- .element: class="fragment" data-fragment-index="1" -->
```javascript=
import * as employeeService from "employee";
employeeService.findAll().then(function(employees) {
console.log(employees);
});
```
<!-- .element: class="fragment" data-fragment-index="1" -->
---
<div class="js-img"></div>
# 類別
----
## ECMAScript 6 類別
```javascript=
class Mortgage {
constructor(amount, years, rate) {
this.amount = amount;
this.years = years;
this.rate = rate;
}
calculate() {
// No interest mortgage for ES6 fans
return this.amount / (this.years * 12);
}
}
let m = new Mortgage(200000, 30, 3);
console.log(m.calculate());
```
----
## ECMAScript 6 類別
```javascript=
class Circle extends Shape {
constructor(x, y, radius) {
super(x, y);
this.radius = radius;
}
static get pi() {
return 3.14159265359;
}
get circumference() {
return 2 * Circle.pi * this.radius;
}
render() {
console.log('Rendering circle');
}
}
```
----
## ECMAScript 6 類別
```javascript=
var c = new Circle(0, 0, 10);
console.log(c.x); // 0
c.x = 5;
console.log(c.x); // 5
console.log(Circle.pi); // 3.14159265359
console.log(c.circumference); // 62.8318530718
c.render(); // Rendering circle
```
---
<div class="js-img"></div>
# 樣板字串
----
## 樣板字串
```javascript=
var str = `Hello World!`
console.log(str);
```
```javascript=
var multiLine = `This is an example
of a multiline string`;
console.log(multiLine);
```
<!-- .element: class="fragment" data-fragment-index="1" -->
----
## 字串替換
```javascript=
var name = "Christophe";
console.log(`Hello, ${name}!`);
```
```javascript=
var user = {firstName: "Lisa", lastName: "Wong"};
console.log(`Hello, ${user.firstName} ${user.lastName}!`);
```
<!-- .element: class="fragment" data-fragment-index="1" -->
----
## 表達式
```javascript=
console.log(`Today is ${new Date()}!`);
```
```javascript=
var price = 100;
var exchangeRate = 0.89;
console.log(`Price in Euro: ${price * exchangeRate}`);
```
<!-- .element: class="fragment" data-fragment-index="1" -->
```javascript=
console.log(`Hello, ${user.firstName} ${user.lastName}!
Today is ${new Date()}`);
```
<!-- .element: class="fragment" data-fragment-index="2" -->
---
<div class="js-img"></div>
# Generators
----
## 什麼是 Generator?
- 使用 *function\** 宣告的特殊函數,屬工廠模式 (Factory Pattern)
- 使用 *yield* 可以在任何地方脫離函數
- 當再次進入時,會回復到與之前相同的點與相同的狀態
----
## Generator 範例
```javascript=
function* idMaker(){
var index = 0;
while(index < 3) {
yield index++;
}
}
var gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // undefined
```
---
<div class="js-img"></div>
# 集合
----
## ES5 "Map"
```javascript=
var settings = {};
settings.server = "http://localhost";
settings.userName = "Christophe";
settings["language"] = "EN";
```
鍵必須是字串
## ES6 Map
<!-- .element: class="fragment" data-fragment-index="1" -->
```javascript=
var map = new Map();
map.set("server", "http://localhost");
map.set("userName", "Christophe");
map.get("userName");
map.has("userName");
map.delete("userName");
```
<!-- .element: class="fragment" data-fragment-index="1" -->
鍵可以是任何東西
<!-- .element: class="fragment" data-fragment-index="1" -->
----
## WeakMap
- 跟 Map 很像
- 鍵必須是物件
- 不會防止鍵被垃圾回收 (GC)
- 對於防止記憶體洩漏很有用
- 不能被迭代 (iterated)
----
## Set
有排序的不重複隨意值
```javascript=
var colors = new Set();
colors.add("red");
colors.add("blue");
console.log(colors.size); // 2;
console.log(colors.has("red")); // true;
colors.delete("red");
```
----
## WeakSet
- 跟 Set 很像
- 值必須是物件
- 不會防止值被垃圾回收 (GC)
- 不能迭代 (iterated)
---
# 參考資料
- [ECMAScript 6 Spec](http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts)
- [ECMAScript 6 on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla)
- [2ality.com](http://www.2ality.com/)
- [ECMAScript 6 Tools](https://github.com/addyosmani/es6-tools)
- [Babel](http://babeljs.io/)
- [Traceur](https://github.com/google/traceur-compiler)
---
## 謝謝!歡迎指教
[@jackymaxj](https://twitter.com/jackymaxj)
原作者:[@ccoenraets](https://twitter.com/ccoenraets)
> 喜歡這份簡報嗎?你也來寫一份吧!
> https://goo.gl/CfG0hH
{"metaMigratedAt":"2023-06-14T11:35:59.519Z","metaMigratedFrom":"Content","title":"ECMAScript 6 簡介","breaks":"true","contributors":"[]"}