速習
ESNext
Ryo Utsunomiya(@ryo511)
Gutenberg MeetUp vol.2
2018-05-09
ESNextとは
ES5落穂拾い
ES2015+
ESNextとGutenberg
const object1 = {};
// 書き込み不可プロパティを定義
Object.defineProperty(object1, 'property1', {
value: 42,
writable: false
});
// 書き込み不可(strictモードではエラーになる)
object1.property1 = 77;
console.log(object1.property1); // 42
var user = {
firstName: 'John',
lastName: 'Smith',
get fullName() {
return this.firstName + ' ' + this.lastName;
}
set fullName(value) {
var names = value.split(' ');
this.firstName = names[0];
this.lastName = names[1];
}
};
console.log(user.fullName); // John Smith
user.fullName = 'Jack Johnson';
console.log(user.firstName, user.lastName); // Jack, Johnson
var user = {
firstName: 'John',
lastName: 'Smith',
};
console.log(Object.keys(user)); // firstName, lastName
// Object.keys + Array.forEachによるオブジェクトの走査
Object.keys(user).forEach(function(key) {
console.log(user[key]); // John, Smith
});
// ↑と同等のES3コード
for(var key in user) {
// このチェックがないとprototypeのプロパティも列挙してしまう
if(user.hasOwnProperty(key)) {
console.log(user[key]);
}
}
// ES3
console.log(Object.prototype.toString.call([]) === '[object Array]'); // true
console.log(Object.prototype.toString.call({}) === '[object Array]'); //false
// ES5
console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false
var a = [1,2,3,4,5];
a.forEach(function(n) {
console.log(n); // 1,2,3,4,5
});
var a = [1,2,3,4,5];
var even = a.filter(function(n) {
return n % 2 === 0; // 偶数のみ絞り込み
});
console.log(even); // 2,4
var a = [1,2,3,4,5];
var double = a.map(function(n) {
return n * 2; // 配列の全要素を2倍にする
});
console.log(double); // 2,4,6,8,10
var a = [1,2,3,4,5];
var sum = a.map(function(accumulator, current) {
return accumulator+ current;
});
console.log(sum); // 15
var a = [1,2,3,4,5];
var evenDoubleSum = a.filter(function(n) {
return n % 2 === 0; // 偶数のみ絞り込み => [2,4]
}).map(function(n) {
return n * 2; // 2倍 => [4,8]
}).reduce(function(accumulator, current) {
return accumulator + current; // 4 + 8
});
console.log(evenDoubleSum); // 12
// ES2015のアロー関数式を使うとよりシンプルに
const evenDoubleSum = a.filter(n => n % 2 === 0)
.map(n => n * 2)
.reduce((a, c) => a + c);
関数を短く書ける
// ES5
var hello = function() { return 'Hello' };
// ES2015: アロー関数式の基本形、function() を ()=>と省略できる
const hello = () => { return 'Hello' };
console.log(hello()); // Hello
// ES5
var greet = function(greeting) { return greeting };
// ES2015:引数が1つの場合は括弧を省略可能
const greet = greeting => { return greeting };
console.log(greeting('Good morning')); // 'Good morning'
// ES5
var greetWithName = function(greeting, name) {
return greeting + ', ' + name + '!';
};
// ES2015:関数本体が1行の場合は、{return}を省略可能
const greetWithName = (greeting, name) => `${greeting}, ${name}!`;
console.log(greetWithName('Good morning', 'John')); // Good morning, John!
関数のデフォルト引数を設定できる
// ES5
function greet(name, greeting) {
if (greeting === undefined) greeting = 'Hello'; // greetingのデフォルト値設定
return greeting + ', ' + name + '!';
}
// ES2015
// greetingが渡されなかった(undefined)場合はHelloになる
function greet(name, greeting = 'Hello') {
return `${greeting}, ${name}!`; // テンプレートリテラル(後述)
}
console.log(greet('John')); // Hello, John
console.log(greet('John', 'Good morning')); // Good morning, John
関数パラメータの「余り」をまとめて取得できる
// ES5
function sum() {
var n = 0;
// argumentsはArrayではないので、for文で走査する
for (var i = 0; i < arguments.length; i += 1) {
n += arguments[i];
}
return n;
}
// ES2015
function sum(...args) {
// argsはArrayなので、配列操作メソッドが呼べる
return args.reduce((a, c) => a + c);
}
console.log(sum(1)); // 1
console.log(sum(2, 3)); // 5
const, letはブロックスコープ
// ES5
var a = 'a';
a = 'b'; // OK
for (var i = 0; i < 5; i += 1) {
console.log(i);
}
console.log(i); // 4
// ES2015
const a = 'a';
a = 'b'; // 再代入不可エラー
for (let i = 0; i < 5; i += 1) {
console.log(i);
}
console.log(i); // undefined
オブジェクトコンストラクタの糖衣構文
// ES5
function Person(name) {
this.name = name;
}
// ES2015
class Persoon {
constructor(name) {
this.name = name;
}
}
// 使い方は同じ
const aPersoon = new Person('John');
extendsキーワードを使って、既存オブジェクトの機能を引き継いだオブジェクトを作成できる
// React.Componentを継承した新しいクラスを定義
class MyComponent extends React.Component {
// ...
}
変数を文字列内に埋め込める
// ES5
var name = 'John';
var greeting = 'Hello, ' + name + '.' + '\n' +
'Nice to meet you!';
// ES2015
const name = 'John';
const greeting = `
Hello, ${name}.
Nice to meet you!`;
var array = [1, 2];
// ES5
var a = array[0];
var b = array[1];
// ES2015
const [a, b] = array;
// Promise.all の結果を受け取ったりするのに便利
const [result1, result2] = await Promise.all([
doSomething1(),
doSomething2(),
]);
var obj = {
a: 1,
b: {
foo: 'bar',
},
};
// ES5
var a = obj.a;
var foo = obj.b.foo;
// ES2015
const { a } = obj; // 変数 a が定義され、1が入る
const { b: { foo } } = obj; // 変数 foo が定義され、'bar'が入る
// 関数の引数でも使える
function createDate({ year, month, day }) {
return new Date(year, month + 1, day);
}
createDate({ year: 2017, month: 5, day: 9 });
// jQueryを$という変数名で読み込み
import $ from 'jqeury';
// math.js
const sum = ...args => args.reduce((p, c) => p + c);
export sum;
// index.js
// math.jsでexportされている関数をまとめてオブジェクトにしてmath変数に代入
import * as math from './math.js';
math.sum(1, 2); // 3
// オブジェクトの分割代入を使用すれば直接importできる
import { sum } from './math.js';
// sum.js
const sum = ...args => args.reduce((p, c) => p + c);
export default sum;
// index.js
import sum from './sum.js';
$.get('http://api.example.com/auth', function(result1) {
if (result1.isAuthenticated) {
// ログイン済みならユーザ情報を取得
$.get('http://api.example.com/me', function(result2) {
if (result2.userData) {
// ユーザーデータをどこかに送信
$.post('http://api.example.com/log', result.userData, function(result3) {
// さらに処理が続く...
})
}
});
}
});
// 1秒後にランダムで成功/失敗するオブジェクト
var p = new Promise((resolve, reject) => {
setTimeout(() => {
if (Date.now() % 2 === 0) {
resolve('even');
} else {
reject('odd');
}
}, 1000);
});
p.then(result => console.log(result)) // thenで設定した関数がresolveになる
.catch(error => console.error(error)); // catchで設定した関数がrejectになる
// 1秒後に結果が表示される
// Promiseを使ってもコールバック地獄と大差ないコード...
$.get('http://api.example.com/auth')
.then(result1 => {
$.get('http://api.example.com/me')
.then(result2 => {
// ...
});
// 1秒後にランダムで成功/失敗するオブジェクト
var p = new Promise((resolve, reject) => {
setTimeout(() => {
if (Date.now() % 2 === 0) {
resolve('even');
} else {
reject('odd');
}
}, 1000);
});
(async () => {
const result = await p.catch(e => console.error(e));
if (result) console.log(result);
})();
const auth = await $.get('http://api.example.com/auth');
if (auth.isAuthenticated) {
const userData = await $.get('http://api.example.com/me');
if (userData) {
const result = await $.post('http://api.example.com/log', result.userData);
// 結果に応じた処理...
}
}