ECMAScript とは
えくますくりぷと。
JavaScript の言語仕様。Ecma Internationl によって標準化手続きが行われている。
ECMAScript をもとに実装されている他の言語には ActionScript や JScript などがある。
ES2015(ES6) とは
ECMAScript 6th Edition のこと。
2015年に仕様策定されたため、正式名称を ECMAScript 2015(ES2015) とし、今後は年単位での細かいリリースが計画されている。
現在、一般的に利用されている JavaScript は ES5 を元にしており、ES2015 は次世代の JavaScript という位置づけになる。
複雑で高機能化するWebアプリケーションの開発に応えるため、ES2015 では様々な機能追加や修正が行われている。
ES2015 で追加された主な機能
let
, const
による変数宣言
-
let
は再宣言が不可能な変数宣言 -
const
は再宣言と再代入が不可能な変数宣言
var val = 'variable1';
console.log(variable1); // variable1
val = 'variable2'; // 再代入
console.log(val); // variable2
var val = 'variable3'; // 再宣言
console.log(val); // variable3
let val = 'variable1';
console.log(variable1); // variable1
val = 'variable2'; // 再代入
console.log(val); // variable2
let val = 'variable3'; // 再宣言でエラー
const val = 'variable1';
console.log(variable1); // variable1
val = 'variable2'; // 再代入でエラー
ブロックスコープ
{}
(ブラケット)によるブロックスコープが有効になる(スタンドアロンのブラケットでもブロックが生成される)。
ブロック内でlet
, const
を利用して宣言された変数のスコープは、そのブロック内に絞られる。
{
var val1 = 1;
let val2 = 2;
const val3 = 3;
console.log(val1); // 1
console.log(val2); // 2
console.log(val3); // 3
}
console.log(val1); // 1
console.log(val2); // undefined
console.log(val3); // undefined
テンプレートリテラル
` `
(バッククォート)で囲われた文字列内では、${}
で変数展開ができる。改行も反映される。
var version = 'ES5';
console.log('JS version is ' + version); // JS version is ES5
const version = 'ES2015';
console.log(`JS version is ${version}`); // JS version is ES2015
console.log(`JS
version
is
${version}`); // JS
// version
// is
// ES2015
for...of
反復可能なオブジェクトに対する処理が、より直感的にできるようになった。
var array = [65, 55, 80, 100];
for(var index in array) {
console.log(index, array[index]);
}
// 0 65
// 1 55
// 2 80
// 3 100
array.forEach(function (value, index) {
console.log(index, value);
});
// 0 65
// 1 55
// 2 80
// 3 100
var obj = {
country: 'Japan',
language: 'Japanese'
};
for(var key in obj) {
console.log(key, obj[key]);
}
// country Japan
// language Japanese
const array = [65, 55, 80, 100];
for(const value of array) {
console.log(value);
}
// 65
// 55
// 80
// 100
// for...of ではオブジェクトのプロパティ値は処理できないので、従来通りのやり方で
アロー関数
従来のfunction
より簡素な記述で関数が定義できる。
// 従来の function を使った書き方
var plus = function(x, y) {
return x + y;
};
// アロー関数で function を省略
let plus = (x, y) => {
return x + y;
};
// 単一式の場合はブラケットや return を省略できる
let plus = (x, y) => x + y;
// 引数が1つの場合は、仮引数の () も省略できる
let square = num => num * num;
this
の束縛
従来のthis
は実行時の呼び出し元に紐付けられていたが、アロー関数では関数宣言時のthis
スコープを引き継ぐため、bind(this)
でthis
を束縛したり、self, that, _this などの別変数でthis
を退避する必要がなくなった。
var counter = {
count: 0,
start: function() {
// thisを別名で退避
var self = this;
setTimeout(function() {
// this.count++;
// 実行時の呼び出し元は window オブジェクトであり、
// この場合での this は counter オブジェクトではないため、
// 退避した変数 self を使用する必要がある
self.count++;
}, 1000);
}
};
var counter = {
count: 0,
start: function() {
setTimeout(() => {
this.count++;
}, 1000);
}
};
デフォルト引数
関数の引数に省略時のデフォルト値が設定できる。
function square (num = 5) {
return num * num;
}
console.log(square()); // 25
console.log(square(10)); // 100
スプレッド演算子 ...
式が置かれるところで値が展開される。
可変長引数(レストパラメータ)
関数の仮引数にスプレッド演算子を利用すると、可変長引数を配列で受け取ることができる。
function func1 (...params) {
console.log(params);
console.log(params[0]);
}
func1(1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]
// 1
function func2 (val, ...params) {
console.log(val);
console.log(params);
}
func2(1, 2, 3, 4, 5); // 1
// [2, 3, 4, 5]
配列展開
スプレッド演算子を利用すると、配列の展開ができる。
var array = [1, 10, 3];
console.log(array); // [1, 10, 3]
console.log(Math.max(1, 10, 3)); // 10
console.log(Math.max(array)); // NaN
console.log(Math.max.apply(null, array)); // 10
// apply() は、第2引数の配列の中身が引数として渡される
const array = [1, 10, 3];
console.log(...array); // 1 10 3
console.log(Math.max(1, 10, 3)); // 10
console.log(Math.max(array)); // NaN
console.log(Math.max(...array)); // 10
function func (x, y, z) {
console.log(x);
console.log(y);
console.log(z);
}
func(...array); // 1
// 10
// 3
分割代入
分割代入時にスプレッド演算子を利用すると、複数の値を1つの配列にまとめられる。
const [a, b, ...c] = ['a', 'b', 'c', 'C'];
console.log(a); // a
console.log(b); // b
console.log(c); // ['c', 'C']
配列の結合
スプレッド演算子を利用すると、配列の結合が簡単にできる。
var array = [1, 2, 3];
var array2 = array.concat([4, 5, 6]);
console.log(array2); // [1, 2, 3, 4, 5, 6]
const array = [1, 2, 3];
const array2 = [...array, 4, 5, 6];
console.log(array2); // [1, 2, 3, 4, 5, 6]
class
によるクラス宣言
従来の prototype ベースの構文より、簡潔で馴染みのある記述でクラスを定義できる。
// 従来の prototype ベースの構文
var Person = function(name) {
this.name = name;
};
Person.prototype.getName = function() {
return this.name;
};
Person.prototype.greeting = function() {
console.log(`Hello, I am ${this.getName()}`);
};
// Class構文
class Person {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
greeting() {
console.log(`Hello, I am ${this.getName()}`);
}
}
extends
を利用したクラスの継承
class Person {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
greeting() {
console.log(`Hello, I am ${this.getName()}`);
}
}
// Person を継承
class Man extends Person {
greeting() {
console.log(`Hi, I am ${this.getName()}`);
}
}
const man = new Man('Bob');
man. greeting(); // Hi, I am Bob
その他、ES2015 で追加された機能など
-
Number
の拡張ES2015.jsNumber.EPSILON; // 1と Number として表現できる1より大きい最小の値の差 Number.isInteger(Infinity); // false Number.isNaN('NaN'); // false
-
Math
の拡張ES2015.jsMath.acosh(3); // ハイパボリックアークコサイン (双曲線逆余弦): 1.762747174039086 Math.hypot(3, 4); // 引数の二乗和の平方根: 5 Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2); // 32ビット乗算: 2
-
String
の拡張ES2015.js'abcde'.includes('cd'); // true 'abc'.repeat(3); // 'abcabcabc'
-
Array
の拡張ES2015.jsArray.from(document.querySelectorAll('*')); // 配列型や反復型オブジェクトから新しい Array インスタンスを生成 Array.of(1, 2, 3); // 可変個の引数から新しい Array インスタンスを生成 [0, 0, 0].fill(7, 1); // 開始位置〜終了位置を指定値で埋める: [0,7,7] [1, 2, 3].find(x => x == 3); // テスト関数を満たす、配列中の要素を返却: 3 [1, 2, 3].findIndex(x => x == 2); // テスト関数を満たす、配列中の要素のインデックスを返却: 1 [1, 2, 3, 4, 5].copyWithin(3, 0); // 配列内の要素の並びを指定位置にコピー: [1, 2, 3, 1, 2] ['a', 'b', 'c'].entries(); // 新しい Array Iterator オブジェクトを返却: [0, 'a'], [1, 'b'], [2, 'c']のイテレータ ['a', 'b', 'c'].keys(); // 新しい Array Iterator オブジェクトを返却(各 key を保持): 0, 1, 2 のイテレータ ['a', 'b', 'c'].values(); // 新しい Array Iterator オブジェクトを返却(各 value を保持): 'a', 'b', 'c'のイテレータ
-
Object
の拡張ES2015.jsObject.assign(Point, { origin: new Point(0,0) }); // 一つ以上のソースオブジェクトから、直接所有(own)で列挙可能(enumerable)なすべてのプロパティ値をコピー
-
イテレータ(
.next()
,.values()
)- 現在の処理位置を把握しつつ、コレクション中の項目へ順にアクセスする方法を備えたオブジェクト
-
ジェネレータ(
function*
,yield
)- イテレータを返す特別な関数
-
マップオブジェクト(
Map()
,WeekMap()
)- key - value のコレクション
-
Object
と似ているが少し違う
-
セットオブジェクト(
Set()
,WeekSet()
)- ユニークなデータのコレクション
-
import
とexport
によるモジュール構文- 外部モジュールや関数、オブジェクト、プリミティブのインポート/エクスポートを行う
-
シンボル(
Symbol()
)- ユニークで不変なデータ型
- オブジェクトのプロパティ識別子などで使われる
- Ruby: どれだけ作っても必ず同じオブジェクトになるもの
- JS: 二度と同じオブジェクトを生成できないもの
-
プロキシ(
Proxy()
)- オブジェクトが持つ機能を独自に定義できる
-
リフレクト(
Reflect
)- オブジェクトが本来持つ機能を返す
-
非同期処理(
Promise()
) -
正規表現での Unicode 対応