速習ECMAScript6: 次世代の標準JavaScriptを今すぐマスター! [Kindle版]
を読みながら、実際に色々試してみたときのメモ。
上記本は250円でサクッと読め、サンプルコードもあり、実際に試しながら進めるととても良かったです。
なお、BebelなどのトランスコンパイラーやPolyfillライブラリを使用は使用せず、確認。
環境
- Node v4.2.2
基本構文
ブロックレベルのスコープの変数宣言(let)
今までのJSではブロックレベルのスコープがなかったが、let
で変数宣言すると可能になった。
if (1) {
var i = 1;
}
console.log(i); // 1と表示されてしまう
'use strict'
if (1) {
let i = 1;
}
console.log(i); // error. i is not defined
今後はvar
ではなく、基本的にlet
を使った方が良さそう。
定数の宣言(const)
const
を使うことで定数の宣言ができ、変数に値を再代入しようとするとエラーにしてくれる
'use strict'
const FUGA = 1;
FUGA = 10; // error.Assignment to constant variable
文字列への変数の埋め込み・改行の埋め込み
今まで文字列連結では文字列の変数同士を+演算子で囲っていたが、文字列内に変数を埋め込むことができるようになった。
また、改行をそのまま書くことも可能。
'use strict';
let name = 'hoge';
console.log('hello ' + name); // hello hoge
console.log(`hello ${name}`); // hello hoge
let str = `hello
hoge`;
console.log(str); // hello(改行) hoge
- 「`」で文字列を囲むとテンプレート文字列として改行や変数の埋め込みが出来る
- 変数は${変数名}という記述で書ける
新しい型のSymbol
ES6ではSymbolという型が追加された。
'use strict';
let hoge = Symbol('hoge'); //Symbolの生成
console.log(typeof hoge); // symbol
let hoge2 = Symbol('hoge');
console.log(hoge === hoge2); // false
- Symbol()でシンボルの生成
- 同じ引数でSymbolを生成しても、オブジェクトが違えば別の物として扱われる
上記の使い方として定数としての使い方が考えられる。
'use strict';
const TOKYO = Symbol();
const KANAGAWA = Symbol();
const SAITAMA = Symbol();
// TOKYOの場合の処理
if(hoge === TOKYO) {
}
上記ではSymbol()
として引数は渡していないが、それぞれのSymbolは別物として扱われる。
また、クラスの非公開プロティの定義として利用できる
'use strict';
const SECRET = Symbol();
class Person {
constructor(secret) {
this.data1 = 1;
this.data2 = 2;
this[SECRET] = secret;
}
isSecret(secret) {
return this[SECRET] === secret;
}
}
let person1 = new Person('password');
console.log(person1.isSecret('password')); // true
console.log(person1.data1); // 1
console.log(person1.data2); // 2
console.log(person1[SECRET]); // 別ファイルだとSECRETのSymbolが不明なので読み込めない
分割代入
Node4.2だとエラーになってしまった。。。
let [hoge1, hoge2] = [15, 21]; // Unexpected token [
確かに公式を見ても分割代入(destructuring assignment)という単語はないので未サポートなのかな。。
関数
引数のデフォルト値の宣言
これもダメやった。。。
'use strict';
function show(title = 'Star wars') {
return `I like ${title}`;
}
console.log(show());
$node test.js
function show(title = 'Star wars') {
^
SyntaxError: Unexpected token =
・・・
可変長引数
これもダメー。
'use strict';
function sum(...args) {
//let result = 0;
console.log(args);
}
console.log(sum(10, 20, 30));
$node test.js
function sum(...args) {
^^^
SyntaxError: Unexpected token ...
・・・
アロー関数
Node.jsなどでもよく書く
function(arg1,arg2) {処理}
という書き方を
(arg1, arg2) => 処理
という形で書ける。
また、処理が1文の場合にはreturn文が不要になる。
例えば以下のように書いていたものを
use strict';
setInterval(function() {
console.log('hoge');
}, 100);
このように書ける。
'use strict';
setInterval(() =>
console.log('hoge'),
100);
こうでもOK
setInterval(() => console.log('hoge'), 100);
組み込みオブジェクト
Promise
難しかったので別途書きました。
Proxyオブジェクト
これも書いてないし、未対応っぽい。
コレクション(Map/Setなど)
以下が対応しているっぽい。
- Map
- WeakMap
- Set
- WeakSet
上記は知っているので省略。
String,Array,Mathなどの組み込みオブジェクトのメソッド拡充
色々メソッドが増えた。
Stringだと以下が便利そう。
- repeat(num)->文字列を指定回数だけ繰り返したものを生成
- startsWith(search. [,pos])->文字列が部分文字列searchで始まるか
- endsWith(search. [,pos])->文字列が部分文字列searchで終わるか
- includes(search. [,pos])->文字列が部分文字列searchが含まれるか
'use strict';
let str = 'starwars';
// repeat
console.log(str.repeat(2)); //starwarsstarwars
// starts
console.log(str.startsWith('st')); // true
console.log(str.startsWith('war')); // false
// ends
console.log(str.endsWith('wars')); // true
console.log(str.endsWith('star')); // false
// include
console.log(str.includes('star')); // true
console.log(str.includes('hoge')); // false
ArrayではfindやfindIndexが便利そう
- find(callback(element, index, array))->コールバック関数で最初にtrueを返した要素を返却する
- findIndex(callback(element, index, array))->コールバック関数で最初にtrueを返したindexを返却する
'use strict';
let heros = [
'bat man',
'spider man',
'iron man',
'captain america'
];
// 存在する
const result = heros.find((hero) => {
return hero === 'bat man';
});
const resultIndex = heros.findIndex((hero) => {
return hero === 'bat man';
});
console.log(result); // bat man
console.log(resultIndex); // 0
// 存在しない
const result2 = heros.find((hero) => {
return hero === 'super man';
});
const resultIndex2 = heros.findIndex((hero) => {
return hero === 'super man';
});
console.log(result2); // undefined
console.log(resultIndex2); // -1
オブジェクト指向構文
Classの利用
オブジェクト指向のプログラミングで使えるクラスが対応。
以下のように使える。
'use strict';
class Hoge {
constructor(){
this.data1 = 1;
}
}
module.exports = Hoge;
'use strict';
let Hoge = require('./hoge');
let hoge1 = new Hoge();
console.log(hoge1.data1); // 1
以下も可能
- static修飾子をつけて静的メソッドの定義
- getter/setterの利用
- extendsを利用したクラスの継承
Generator(ジェネレーター)
こちらを参考に書いてみる。
'use strict';
function* idMarker() {
var index = 0;
while(index < 3) {
yield index++;
}
}
var gen = idMarker();
console.log(gen.next()); // { value: 0, done: false }
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: undefined, done: true }
-
function* ...{}
という形式でジェネレーターの利用を宣言 - 通常のfunctionではreturnによって関数の値を呼び出し元に返却して関数が終了する。ジェネレーターでは
yield
を使うことで関数の値を呼び出し元に返すが関数は一時停止となる - yieldによって一時停止させた処理は
next()
を使うことで再開ができる - 返却値にはvalueとdoneプロパティが設定されている。valueにはyieldによって返却された値、doneには再開した関数が終了しているかをbooleanで設定
内容としては分かったが、実際にどう使えば良いかよく分からなかった。。。。
と良い記事があった。(下の記事は以前教えて頂いた)
JavaScriptは如何にしてAsync/Awaitを獲得したのか Qiita版
非同期処理をPromiseで書くこともできるが、問題点もあり、Generatorを組み合わせることで手続き言語のように書くことができる。
tj/coはPromiseとGeneratorの組み合わせた非同期処理を簡単に書けるライブラリで今はこれを使うのが良さそう。
もう少し別で時間が取れたら実際にいろいろ試してみたい。
module(import/export)
Node.jsだとrequire
とかmodule.exports
とかで別ファイルのインポート、エクスポートができたが、それのJavaScript版という感じ?(JavaScriptはあまり書いたことがない。。。)
Class構文の所で書いてみたように利用できる。
ポイントだったこと
- 一部は
'use strict'
の記述をしないと利用できないので注意(常に書くようにした方が楽) - Node 5系でないとサポートしない機能や未サポートのため、BebelなどのトランスコンパイラーやPolyfillライブラリを使用しなければいけないものもある