Hello, ES6

~これから迎えるJSのミライ~

2015.4.25 @yoshiko_pg

突然ですが

JavaScript読めますか?

余裕?

このコード読めますか?

function sum (...nums) {
  return nums.reduce((a, b) => a + b)
}
console.log(sum(1,2,3,4)); // 10


function hi (name = 'Bob') {
  console.log(`Hi, my name is ${name}`);
}
hi('Tom'); // Hi, my name is Tom
hi();      // Hi, my name is Bob

これは?

class Person {
  constructor(name) {
    this.name = name;
  }
  hi() {
    return `Hi, my name is ${this.name}`;
  }
}

class Noisy extends Person {
  hi() {
    return `${super.hi()}!!!!!!!!!`;
  }
}

私の知ってるJavaScriptじゃない

言語は日々進化します

よしこ

よしこ @yoshiko_pg

おしながき

ES6って何

ES6って何

ECMAScriptって何

ES6で何が変わるの

ES6で何が変わるの

ES6の新機能

すっきり書けるよ編

Arrow Function

アロー関数

Arrow Function

// ES5までの書き方
var calc = function(x) {
  return x * 2;
}

// ES6
var calc = (x) => {
  return x * 2;
}

// 省略形
var calc = x => x * 2;

関数の中身の式がひとつの場合、中カッコとreturnを省略できる
引数が1つの場合は引数を囲むカッコを省略できる

// 引数なし
var hi = () => 'hello world!';

// 引数ひとつ
var calc = x => x * 2;

// 引数ふたつ
var add = (a, b) => a + b;

// 1行にまとめても式がふたつ以上なら中カッコが必要
var add = (a, b) => console.log(a, b); a + b; // NG
var add = (a, b) => { console.log(a, b); a + b; } // OK

通常の無名関数とはthisの内容が異なるので注意

var lazyCounter = {
  count: 0,
  countUp: function() { // ここでのthisはlazyCounter
    setTimeout(function() {
      // ここではthisがグローバルオブジェクトになる
      // this.count++; はErrorになる
    }, 10);

    // アロー関数内のthisは外側のthisと同じ
    setTimeout(() => this.count++, 10); // OK
  }
};

lazyCounter.countUp();

Template Strings

テンプレート文字列

Template Strings

// バッククオートで囲む
`simple text` // === 'simple text'

// 複数行
`multiline
text`        // === "multiline\ntext"

// 変数の埋め込み
var count = 1, obj = {foo: 'bar'};
// ES5
'count is ' + count + ', obj.foo is ' + obj.foo;
// ES6
`count is ${count}, obj.foo is ${obj.foo}`;

Default Parameters

デフォルト引数

Default Parameters

//ES5
function twice (x) {
  x = x || 10; // xがfalsyであれば10を代入
  return x * 2;
}
console.log(twice(4), twice(), twice(0));
// 8 20 20(!?)

//ES6
function twice (x = 10) {
  return x * 2;
}
console.log(twice(4), twice(), twice(0));
// 8 20 0

Default Parameters

// デフォルト値のない引数より後にしか置けない
function(x=1, y) {}; // NG
function(y, x=1) {}; // OK

// undefinedを渡した場合はデフォルト値が使用される
function test (value = 'default') {
  console.log(value);
}
test(false); // false
test(null); // null
test(undefined); // 'default'

Rest Parameters

可変長引数

Rest Parameters

rest(1, 2, 3);

function rest (...args) {
  console.log(args); // [1, 2, 3]
  console.log(arguments); // [1, 2, 3]

  console.log(Array.isArray(args)); // true
  console.log(Array.isArray(arguments)); // false

  args.forEach(x => console.log(x)); // 1 2 3
  arguments.forEach(x => console.log(x)); // Error
}

Rest Parameters

function rest(x, y, ...others) {
  console.log(x, y, others);
}

rest(1, 2, 3);  // 1 2 [3]

// 引数が渡らなかった場合は空の配列になる
rest(1);        // 1 undefined []

// 最後の引数以外には使用できない
function rest(first, ...arr, last) {  } // NG

Spread operator

スプレッド演算子

spread: 〈人が〉【場所に】〈物〉を広げる, (一面に)並べる

Spread operator

配列の前に...をつけることで展開できる

var arr = [3, 4, 5];
var nums = [1, 2, ...arr, 6, ...[7]];
console.log(nums); // [1, 2, 3, 4, 5, 6, 7]

Spread operator

applyメソッドを使用しなくても良い

function f(x, y, z) {
  console.log(x, y, z);
}

var args = [1, 2, 3];

// ES5
f.apply(null, args); // 1 2 3

// ES6
f(...args); // 1 2 3

Enhanced
object literals

強化された
オブジェクトリテラル

Enhanced object literals

変数名と同じキーや無名関数のfunctionを省略できる

var name = 'yoshiko', age = 23;

// ES5
var person = {
  name: name,
  age: age,
  hi: function() { return 'hi'; }
};
// ES6
var person = {
  name, age, hi() { return 'hi'; }
};

Enhanced object literals

keyに動的な値を使用できる

var rand = Math.random();

//ES5
var obj = {};
obj[rand] = 'value';

//ES6
var obj = {[rand]: 'value'};
console.log(obj);
// Object {0.2180616082623601: "value"}

var obj2 = {[Math.random()]: 'value'};

Enhanced object literals

他にも色々あるけど省略

詳しい解説:http://wiki.ecmascript.org/doku.php?id=harmony:object_literals

Destructuring

分配束縛

Destructuring

var [a, , b] = [1, 2, 3];
console.log(a, b); // 1 3

function today() { return {y: 2015, m: 4, d: 25}; }
var {y: year, m: month} = today();
console.log(year, month); // 2015 4

// 関数の引数にも使える
function dest({name: name}) {
  console.log(name);
}
var person = {id: 1, name: 'Taro'};
dest(person); // 'Taro'

Destructuring

// 値がなくてもエラーは発生しない
var [c, d] = [4];
console.log(c, d); // 4 undefined

// 値がなかった場合のデフォルト値も指定できる
var [e = 1, f] = [];
console.log(e, f); // 1 undefined

Destructuring

変数の値の入れ替えが楽

var a = 'bbb', b = 'aaa';

// ES5
var tmp = a;
a = b;
b = tmp;

// ES6
[a, b] = [b, a];

console.log(a, b); // aaa bbb

Class

クラス

Class

今までコンストラクタ関数とprototypeを使用して表現してきたクラス構造を、クラス用の構文で定義できる

// ES5
var Person = function(name) {
  this.name = name;
};
Person.prototype.hi = function() {
  return `Hi, my name is ${this.name}`;
};
var bob = new Person('Bob');
console.log(bob.hi()); // Hi, my name is Bob

Class

// ES6
class Person {
  constructor(name) {
    this.name = name;
  }
  hi() {
    return `Hi, my name is ${this.name}`;
  }
}
var tom = new Person('Tom');
console.log(tom.hi()); // Hi, my name is Tom

// あくまでもシンタックスシュガー
console.log(typeof Person); // function

Class

継承もできる

class Noisy extends Person {
  hi() {
    return `${super.hi()}!!!!!!!!!`;
  }
}

var mike = new Noisy('Mike');
console.log(mike.hi()); // Hi, my name is Mike!!!!!!!!!;

ES6の新機能

こんなこともできるよ編

時間がないので割愛

Unicode, Map + Set + WeakMap + WeakSet, Proxies, Subclassable Built-ins, Math + Number + String + Object APIs, Binary and Octal Literals, Reflect API, Tail Calls

知りたい方はこちらがおすすめ

ES6の時代きた!!!
今日から使おう!!!

そのまま書いても
まだ使えません

どうやったら使えるの

ES6実装状況

http://kangax.github.io/compat-table/es6/

BABEL

Babelを使えば今すぐ書ける!

ES6との付き合い方

まずはちょっと試したい

Babel repl http://babeljs.io/repl/

Scratch JS (Chrome Extension)

Scratch JS - Chromeウェブストア

https://github.com/richgilbank/Scratch-JS

Chromeデベロッパーツールにタブが増える
Traceur, Babel, CoffeeScript, LiveScriptから
使用するトランスパイラを選べる

プロダクトのコードに使いたい

gulp-babel

http://github.com/babel/gulp-babel

var gulp = require('gulp');
var babel = require('gulp-babel');

gulp.task('default', function() {
  return gulp.src('./es6/*.js')
    .pipe(babel())
    .pipe(gulp.dest('js'));
});

babelify

http://github.com/babel/babelify

npm install -D babelify
browserify script.js -t babelify -o bundle.js

simple compile

npm install -g babel
babel script.js > compiled.js
node compiled.js

テストだけES6で書いて慣れたい

mocha + babel

mocha --compilers es6:babel/register test.js

mocha + power-assert + babel

npm i -D espower-babel;
mocha --compilers js:espower-babel/guess test.js

https://github.com/azu/espower-babel

mocha + power-assert + babel

// test.js
import assert from 'power-assert';

describe('ES6 Test', () => {
  it('Arrow Function', () => {
    let test = x => x * 2;
    assert(test(4) === 8);
  });

  it('Template String', () => {
    let name = 'Taro';
    assert(`name is ${name}` === 'name is Taro');
  });
});

まとめ

言語は日々進化します

わたしたちの知識も
進化させましょう

俺達の戦いはこれからだ!

Thank you

@yoshiko_pg

Page 1 of 69