<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
{}
    7925 views