この記事は翻訳作業中です。

アロー関数式 は、function 式 より短い構文で、thisarguments, super, new.target を束縛しません。アロー関数は、メソッドでない関数に最適で、コンストラクタとして使うことはできません。

構文

基本的な構文

(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
         // 右と等価: (param1, param2, …, paramN) => { return expression; }

// 引数が 1 個だけの場合、丸括弧 () は任意です:
(singleParam) => { statements }
singleParam => { statements }

// 引数がない場合、丸括弧を書くべきです:
() => { statements }

高度な構文

// object リテラル式を返す場合は、本体を丸括弧 () で囲みます:
params => ({foo: bar})

// 残余引数デフォルト引数 をサポートしています
(param1, param2, ...rest) => { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements }

// 引数リスト内の 分割代入 もサポートしています
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f();  // 6

詳しい構文の例は、ES Wiki の harmony:arrow_function_syntax を参照してください。

説明

hacks.mozilla.orgの "ES6 In Depth: Arrow functions" も参照してください。

2つの理由から、アロー関数が導入されました。1つ目の理由は関数を短く書きたいということ。2つ目の理由は、this を束縛したくないこと。

関数の短縮形

var materials = [
  "Hydrogen",
  "Helium",
  "Lithium",
  "Beryl­lium"
];

materials.map(function(material) { 
  return material.length; 
}); // [8, 6, 7, 9]

materials.map((material) => {
  return material.length;
}); // [8, 6, 7, 9]

materials.map(material => material.length); // [8, 6, 7, 9]

this を束縛しない

アロー関数が登場するまでは、関数ごとに自身の this の値を定義していました(コンストラクタでは新しいオブジェクト、strict モード の関数呼び出しでは undefined、"オブジェクトのメソッド" として呼び出された関数ではそのときのオブジェクト、など)。これは、オブジェクト指向プログラミングをする上で煩わしいということが分かりました。

function Person() {
  // Person() のコンストラクタは、自分のインスタンスを `this` として定義する。
  this.age = 0;

  setInterval(function growUp() {
    // 非 strict モードでは、growUp() 関数は `this` をグローバルオブジェクトとして定義する。
    // Person() コンストラクタが定義した `this` とは違う。
    this.age++;
  }, 1000);
}

var p = new Person();

ECMAScript 3/5 では、この問題は this の値をスコープ内の変数に代入することで解決できました。

function Person() {
  var that = this;
  that.age = 0;

  setInterval(function growUp() {
    // このコールバックは、期待されるオブジェクトの値を
    // `that` 変数で参照する。
    that.age++;
  }, 1000);
}

あるいは、適切な this の値を対象の関数(上の例では growUp() )に渡すように、束縛関数 を作成することもできました。

アロー関数は this を束縛しないので、this は関数を囲っている外での this を意味します。そのため、以下のコードは期待通りに動きます。

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| は person オブジェクトを適切に参照します。
  }, 1000);
}

var p = new Person();

strict モードとの関連

this がレキシカルなものなら、strict モードthis に関する規則は無視されます。

var f = () => {'use strict'; return this};
f() === window; // またはグローバルオブジェクト

他の strict モードの規則は通常通り適用されます。

call や apply からの呼び出し

アロー関数では this は束縛されないので、call()apply() メソッドは引数しか渡せません。this は無視します。

var adder = {
  base: 1,

  add: function(a) {
    var f = v => v + this.base;
    return f(a);
  },

  addThruCall: function(a) {
    var f = v => v + this.base;
    var b = {
      base: 2
    };

    return f.call(b, a);
  }
};

console.log(adder.add(1));         // 2 を出力する
console.log(adder.addThruCall(1)); // やはり 2 を出力する

arguments を束縛しない

アロー関数は、arguments オブジェクト を束縛しません。そのため、この例では、arguments は囲っているスコープでの同名変数への参照にすぎません。

var arguments = 42;
var arr = () => arguments;

arr(); // 42

function foo() {
  var f = (i) => arguments[0]+i; // foo は arguments を暗黙的に束縛している
  return f(2);
}

foo(1); // 3

多くの場合、残余引数arguments  オブジェクトの代わりに使えます。

function foo() { 
  var f = (...args) => args[0]; 
  return f(2); 
}

foo(1); // 2

yield キーワードの使用

yield キーワードはアロー関数の本体で使用されないでしょう (内部で入れ子になった関数が許可されている場合を除く)。結果として、アロー関数はジェネレータとして使用できません。

関数本体

アロー関数は、"簡潔文体 (concise body)" または通常の "ブロック文体 (block body)" のどちらかを持ちます。

ブロック文体は、自動的に値を返しません。明示的に return 文を使用する必要があります:

var func = x => x * x;                  // 簡潔構文、"return" を暗に含みます
var func = (x, y) => { return x + y; }; // ブロック文体では明示的な "return" が必要です

オブジェクトリテラルを返す

短縮構文 params => {object:literal} を使ってオブジェクトリテラルを返そうとしても、期待通りに動作しないことに注意しましょう。

var func = () => {  foo: 1  };
// 呼び出した func() は undefined を返す!
var func = () => {  foo: function() {}  };
// SyntaxError: function 文には名前が必要

これは、括弧 ({}) 内のコードが文の列として構文解析されてしまっているからです(つまり、foo はオブジェクトリテラル内のキーでなく、ラベルとして扱われています)。

オブジェクトリテラルは括弧で囲むのを忘れないでください。

var func = () => ({ foo: 1 });

さらなる例

// 空のアロー関数は undefined を返します
let empty = () => {};

(() => "foobar")() // "foobar" を返します

var simple = a => a > 15 ? 15 : a; 
simple(16); // 15
simple(10); // 10

let max = (a, b) => a > b ? a : b;

// 簡単な配列のフィルタリング、マッピング等

var arr = [5, 6, 13, 0, 1, 18, 23];
var sum = arr.reduce((a, b) => a + b);  // 66
var even = arr.filter(v => v % 2 == 0); // [6, 0, 18]
var double = arr.map(v => v * 2);       // [10, 12, 26, 0, 2, 36, 46]

// さらに簡潔な promise チェーン
promise.then(a => {
  // ...
}).then(b => {
   // ...
});

仕様

仕様書 状態 コメント
ECMAScript 2015 (6th Edition, ECMA-262)
Arrow Function Definitions の定義
標準 Initial definition.
ECMAScript Latest Draft (ECMA-262)
Arrow Function Definitions の定義
現行の標準  

ブラウザの実装状況

機能ChromeEdgeFirefoxInternet ExplorerOperaSafari
基本サポート45 有り221 2 無し3210
Trailing comma in parameters ? ?52 無し ? ?
機能Android webviewChrome for AndroidEdge mobileFirefox for AndroidIE mobileOpera AndroidiOS Safari
基本サポート4545 有り221 2 無し3210
Trailing comma in parameters ? ? ?52 無し ? ?

1. The initial implementation of arrow functions in Firefox made them automatically strict. This has been changed as of Firefox 24. The use of 'use strict'; is now required.

2. Prior to Firefox 39, a line terminator (\n) was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like () \n => {} will now throw a SyntaxError in this and later versions.

関連項目

ドキュメントのタグと貢献者

 最終更新者: TNKSoftware,