Help us understand the problem. What is going on with this article?

今日から始める ES2015(ES6)

More than 3 years have passed since last update.

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 は再宣言と再代入が不可能な変数宣言
ES5.js
var val = 'variable1';
console.log(variable1); // variable1

val = 'variable2'; // 再代入
console.log(val);  // variable2

var val = 'variable3'; // 再宣言
console.log(val);      // variable3

ES2015.js
let val = 'variable1';
console.log(variable1); // variable1

val = 'variable2'; // 再代入
console.log(val);  // variable2

let val = 'variable3'; // 再宣言でエラー
ES2015.js
const val = 'variable1';
console.log(variable1); // variable1

val = 'variable2'; // 再代入でエラー

ブロックスコープ

{}(ブラケット)によるブロックスコープが有効になる(スタンドアロンのブラケットでもブロックが生成される)。
ブロック内でlet, constを利用して宣言された変数のスコープは、そのブロック内に絞られる。

ES2015.js
{
  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

テンプレートリテラル

` `(バッククォート)で囲われた文字列内では、${}で変数展開ができる。改行も反映される。

ES5.js
var version = 'ES5';

console.log('JS version is ' + version); // JS version is ES5
ES2015.js
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

反復可能なオブジェクトに対する処理が、より直感的にできるようになった。

ES5.js
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
ES2015.js
const array = [65, 55, 80, 100];

for(const value of array) {
  console.log(value);
}
// 65
// 55
// 80
// 100

// for...of ではオブジェクトのプロパティ値は処理できないので、従来通りのやり方で

アロー関数

従来のfunctionより簡素な記述で関数が定義できる。

ES5.js
// 従来の function を使った書き方
var plus = function(x, y) {
  return x + y;
};
ES2015.js
// アロー関数で 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を退避する必要がなくなった。

ES5
var counter = {
  count: 0,

  start: function() {
    // thisを別名で退避
    var self = this;

    setTimeout(function() {
      // this.count++;
      // 実行時の呼び出し元は window オブジェクトであり、
      // この場合での this は counter オブジェクトではないため、
      // 退避した変数 self を使用する必要がある

      self.count++;
    }, 1000);
  }
};

ES2015.js
var counter = {
  count: 0,

  start: function() {
    setTimeout(() => {
      this.count++;
    }, 1000);
  }
};

デフォルト引数

関数の引数に省略時のデフォルト値が設定できる。

ES2015.js
function square (num = 5) {
  return num * num;
}

console.log(square());   //  25
console.log(square(10)); // 100

スプレッド演算子 ...

式が置かれるところで値が展開される。

可変長引数(レストパラメータ)

関数の仮引数にスプレッド演算子を利用すると、可変長引数を配列で受け取ることができる。

ES2015.js
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]

配列展開

スプレッド演算子を利用すると、配列の展開ができる。

ES5.js
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引数の配列の中身が引数として渡される
ES2015.js
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つの配列にまとめられる。

ES2015.js
const [a, b, ...c] = ['a', 'b', 'c', 'C'];

console.log(a); // a
console.log(b); // b
console.log(c); // ['c', 'C']

配列の結合

スプレッド演算子を利用すると、配列の結合が簡単にできる。

ES5.js
var array = [1, 2, 3];
var array2 = array.concat([4, 5, 6]);

console.log(array2); // [1, 2, 3, 4, 5, 6]
ES2015.js
const array = [1, 2, 3];
const array2 = [...array, 4, 5, 6];

console.log(array2); // [1, 2, 3, 4, 5, 6]

class によるクラス宣言

従来の prototype ベースの構文より、簡潔で馴染みのある記述でクラスを定義できる。

ES2015.js
// 従来の 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 を利用したクラスの継承

ES2015.js
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.js
  Number.EPSILON;  // 1と Number として表現できる1より大きい最小の値の差
  Number.isInteger(Infinity); // false
  Number.isNaN('NaN'); // false
  • Math の拡張
ES2015.js
  Math.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.js
  Array.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.js
  Object.assign(Point, { origin: new Point(0,0) }); // 一つ以上のソースオブジェクトから、直接所有(own)で列挙可能(enumerable)なすべてのプロパティ値をコピー
  • イテレータ(.next(), .values()
    • 現在の処理位置を把握しつつ、コレクション中の項目へ順にアクセスする方法を備えたオブジェクト
  • ジェネレータ(function*, yield
    • イテレータを返す特別な関数
  • マップオブジェクト(Map(), WeekMap()
    • key - value のコレクション
    • Object と似ているが少し違う
  • セットオブジェクト(Set(), WeekSet()
    • ユニークなデータのコレクション
  • importexport によるモジュール構文
    • 外部モジュールや関数、オブジェクト、プリミティブのインポート/エクスポートを行う
  • シンボル(Symbol()
    • ユニークで不変なデータ型
    • オブジェクトのプロパティ識別子などで使われる
    • Ruby: どれだけ作っても必ず同じオブジェクトになるもの
    • JS: 二度と同じオブジェクトを生成できないもの
  • プロキシ(Proxy()
    • オブジェクトが持つ機能を独自に定義できる
  • リフレクト(Reflect
    • オブジェクトが本来持つ機能を返す
  • 非同期処理(Promise()
  • 正規表現での Unicode 対応

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away