1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
|
---
title: アロー関数
slug: Web/JavaScript/Reference/Functions/Arrow_functions
tags:
- ECMAScript 2015
- Functions
- Intermediate
- JavaScript
- Reference
translation_of: Web/JavaScript/Reference/Functions/Arrow_functions
---
<div>{{jsSidebar("Functions")}}</div>
<p><strong>アロー関数式</strong>は、より短く記述できる、通常の <a href="/ja/docs/Web/JavaScript/Reference/Operators/function">function 式</a>の代替構文です。また、<code><a href="https://wiki.developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/this">this</a></code>, <code><a href="https://wiki.developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a></code>, <code><a href="https://wiki.developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/super">super</a></code>, <code><a href="https://wiki.developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/new.target">new.target</a></code> を束縛しません。アロー関数式は、メソッドでない関数に最適で、コンストラクタとして使うことはできません。</p>
<p>{{EmbedInteractiveExample("pages/js/functions-arrow.html")}}</p>
<h2 id="Syntax" name="Syntax">構文</h2>
<h3 id="Basic_syntax" name="Basic_syntax">基本的な構文</h3>
<pre class="syntaxbox notranslate">(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// 上記の式は、次の式と同等です: => { return expression; }
// 引数が 1 つしかない場合、丸括弧 () の使用は任意です:
(singleParam) => { statements }
singleParam => { statements }
// 引数がない場合、丸括弧を書かねばいけません:
() => { statements }
</pre>
<h3 id="Advanced_syntax" name="Advanced_syntax">高度な構文</h3>
<pre class="syntaxbox notranslate">// object リテラル式を返す場合は、本体を丸括弧 () で囲みます:
params => ({foo: bar})
// <a href="/docs/Web/JavaScript/Reference/Functions/rest_parameters">残余引数</a> と <a href="/docs/Web/JavaScript/Reference/Functions/Default_parameters">デフォルト引数</a> をサポートしています
(param1, param2, ...rest) => { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => {
statements }
// 引数リスト内の<a href="/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">分割代入</a>もサポートしています
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f(); // 6
</pre>
<h2 id="Description" name="Description">説明</h2>
<p><a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">hacks.mozilla.org の "ES6 In Depth: Arrow functions"</a> も参照してください。</p>
<p>2 つの理由から、アロー関数が導入されました。1 つ目の理由は関数を短く書きたいということで、2 つ目の理由は <code>this</code> を束縛したくない、ということです。</p>
<h3 id="Shorter_functions" name="Shorter_functions">関数の短縮形</h3>
<pre class="brush: js notranslate">var elements = [
'Hydrogen',
'Helium',
'Lithium',
'Beryllium'
];
elements.<a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(function(element) {
return element.length;
}); // このステートメントが返す配列: [8, 6, 7, 9]
// 上記の通常の関数は、以下のアロー関数として記述できます
elements.map((element) => {
return element.length;
}); // [8, 6, 7, 9]
// パラメータが一つしか無い場合、周囲の括弧を削除できます:
elements.<a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(element => {
return element.length;
}); // [8, 6, 7, 9]
// アロー関数の唯一のステートメントが `return` の場合、 `return` を削除し
// 周囲の波括弧も削除できます
elements.map(element => element.length); // [8, 6, 7, 9]
// この場合、必要なのは length property のみなので、分割パラメータを使用できます:
// 文字列 `"length"` は取得したいプロパティに対応しますが
// 明らかに特別でない `lengthFooBArX` は、任意の有効な変数名に
// 変更可能な変数名です
elements.<a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(({ "length": lengthFooBArX }) => lengthFooBArX); // [8, 6, 7, 9]
// この分割パラメータの代入は、以下のように記述することも可能です。ただし、この例では、
// 作成されたプロパティに `length` の値を代入していないことに注意して下さい。代わりに、
// 変数 `length` のリテラル名自体が、オブジェクトから取得するプロパティとして使用されます。
elements.<a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(({ length }) => length); // [8, 6, 7, 9]
</pre>
<h3 id="No_separate_this" name="No_separate_this"><code>this</code> を束縛しない</h3>
<p>アロー関数以前は、関数の呼び出し方法に応じて自身の <code><a href="https://wiki.developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/this">this</a></code> 値を定義していました</p>
<ul>
<li>コンストラクタでは新しいオブジェクト</li>
<li><a href="/docs/Web/JavaScript/Reference/Strict_mode">strict モード</a> の関数呼び出しでは <code>undefined</code></li>
<li>「オブジェクトのメソッド」として呼び出された関数ではそのときのオブジェクト</li>
<li>など</li>
</ul>
<p>これは、オブジェクト指向プログラミングをする上で煩わしいということが分かりました。</p>
<pre class="brush: js notranslate">function Person() {
// Person() のコンストラクタは、自分のインスタンスを `this` として定義する。
this.age = 0;
setInterval(function growUp() {
// 非 strict モードでは、growUp() 関数は `this` を
// グローバルオブジェクトとして定義する。
// (そこで grouUp()が実行されているため)
// Person() コンストラクタが定義した `this` とは違う。
this.age++;
}, 1000);
}
var p = new Person();</pre>
<p>ECMAScript 3/5 では、この問題は <code>this</code> の値をスコープ内の変数に代入することで解決できました。</p>
<pre class="brush: js notranslate">function Person() {
var that = this;
that.age = 0;
setInterval(function growUp() {
// このコールバックは、期待されるオブジェクトの値を
// `that` 変数で参照する。
that.age++;
}, 1000);
}</pre>
<p>あるいは、適切な <code>this</code> の値を対象の関数(上の例では <code>growUp()</code> 関数)に渡すように、<a href="/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">束縛関数</a>を作成することもできました。</p>
<p>アロー関数自身は <code>this</code> を持ちません。レキシカルスコープの <code>this</code> 値を使います。つまり、アロー関数内の <code>this</code> 値は通常の変数検索ルールに従います。このためスコープに <code>this</code> 値がない場合、その一つ外側のスコープで <code>this</code> 値を探します。</p>
<p>そのため、次のコードで <code>setInterval</code> に渡される関数の <code>this</code> の値は、外部関数の <code>this</code> と同じ値になります:</p>
<pre class="brush: js notranslate">function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| は person オブジェクトを適切に参照します。
}, 1000);
}
var p = new Person();</pre>
<h4 id="Relation_with_strict_mode" name="Relation_with_strict_mode">strict モードとの関連</h4>
<p><code>this</code> がレキシカルなもので与えられる場合、<a href="/docs/Web/JavaScript/Reference/Strict_mode">strict モード</a>の <code>this</code> に関する規則は無視されます。</p>
<pre class="brush: js notranslate">var f = () => { 'use strict'; return this; };
f() === window; // またはグローバルオブジェクト</pre>
<p>他の strict モードの規則は通常通り適用されます。</p>
<h4 id="Invoked_through_call_or_apply" name="Invoked_through_call_or_apply">call や apply からの呼び出し</h4>
<p>アロー関数は自身で <code>this</code> を持たないので、<code>call()</code> や <code>apply()</code> メソッドは引数しか渡せません。<code>this</code> は無視されます。</p>
<pre class="brush: js notranslate">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 を出力する</pre>
<h3 id="No_binding_of_arguments" name="No_binding_of_arguments"><code>arguments</code> を束縛しない</h3>
<p>アロー関数は自身で <a href="/docs/Web/JavaScript/Reference/Functions/arguments"><code>arguments</code> オブジェクト</a>を持ちません。そのため、この例では、<code>arguments</code> は囲っているスコープでの同名変数への参照にすぎません。</p>
<pre class="brush: js notranslate">var arguments = [1, 2, 3];
var arr = () => arguments[0];
arr(); // 1
function foo(n) {
var f = () => arguments[0] + n; // foo は arguments を暗黙的に束縛している。arguments[0] は n である。
return f();
}
foo(3); // 6
</pre>
<p>多くの場合、<a href="/docs/Web/JavaScript/Reference/Functions/rest_parameters">残余引数</a>が <code>arguments</code> オブジェクトの代わりに使えます。</p>
<pre class="brush: js notranslate">function foo(n) {
var f = (...args) => args[0] + n;
return f(10);
}
foo(1); // 11</pre>
<h3 id="Arrow_functions_used_as_methods" name="Arrow_functions_used_as_methods">メソッドとして使われるアロー関数</h3>
<p>前に述べたように、アロー関数式は非メソッド型の関数に最もよく合っています。これをメソッドとして使った時のことを見てみましょう:</p>
<pre class="brush: js notranslate">'use strict';
var obj = {
i: 10,
b: () => console.log(this.i, this),
c: function() {
console.log(this.i, this);
}
};
obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}
</pre>
<p>アロー関数は自身の <code>this</code> を持ちません。{{jsxref("Object.defineProperty()")}} を使う例です。</p>
<pre class="brush: js notranslate">'use strict';
var obj = {
a: 10
};
Object.defineProperty(obj, 'b', {
get: () => {
console.log(this.a, typeof this.a, this); // undefined 'undefined' Window {...} (or the global object)
return this.a + 10; // represents global object 'Window', therefore 'this.a' returns 'undefined'
}
});
</pre>
<h3 id="Use_of_the_new_operator" name="Use_of_the_new_operator"><code>new</code> 演算子の使用</h3>
<p>アロー関数はコンストラクタとして使用できず、<code>new</code> と共に使うとエラーになります。</p>
<pre class="brush: js notranslate">var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor</pre>
<h3 id="Use_of_prototype_property" name="Use_of_prototype_property"><code>prototype</code> プロパティの使用</h3>
<p>アロー関数には <code>prototype</code> プロパティはありません。</p>
<pre class="brush: js notranslate">var Foo = () => {};
console.log(Foo.prototype); // undefined
</pre>
<h3 id="Use_of_the_yield_keyword" name="Use_of_the_yield_keyword"><code>yield</code> キーワードの使用</h3>
<p>{{jsxref("Operators/yield", "yield")}} キーワードはアロー関数内で使用できません(内部で入れ子になった関数が許可されている場合を除く)。結果として、アロー関数はジェネレーターとして使用できません。</p>
<h2 id="Function_body" name="Function_body">関数の Body 部分</h2>
<p>アロー関数は、「簡潔文体 (concise body)」か、もしくはより一般的な「ブロック文体 (block body) 」のどちらかを使用することができます。</p>
<p>簡潔文体 (concise body) においては、単一の式だけが記述できるので、その式が明示的に return される値となります。しかし、ブロック文体においては、自動的に return はされないので、明示的に <code>return</code> 文を使用する必要があります。</p>
<pre class="brush: js notranslate">var func = x => x * x;
// 簡潔構文の場合、明示せずとも"return" されます
var func = (x, y) => { return x + y; };
// ブロック文体では、明示的に "return" を宣言する必要があります
</pre>
<h2 id="Returning_object_literals" name="Returning_object_literals">オブジェクトリテラルを返す</h2>
<p>短縮構文 <code>params => {object:literal}</code> を使ってオブジェクトリテラルを返そうとしても、期待通りに動作しないことに注意しましょう。</p>
<pre class="brush: js notranslate">var func = () => { foo: 1 };
// 呼び出した func() は undefined を返す!
var func = () => { foo: function() {} };
// SyntaxError: function 文には名前が必要
</pre>
<p>これは、括弧 ({}) 内のコードが文の列として構文解析されてしまっているからです(つまり、<code>foo</code> はオブジェクトリテラル内のキーでなく、ラベルとして扱われています)。</p>
<p>オブジェクトリテラルは括弧で囲むのを忘れないでください。</p>
<pre class="brush: js notranslate">var func = () => ({ foo: 1 });</pre>
<h2 id="Line_breaks" name="Line_breaks">改行</h2>
<p>アロー関数には括弧とアロー(矢印)の間に改行を入れられません。</p>
<pre class="brush: js notranslate">var func = ()
=> 1;
// SyntaxError: expected expression, got '=>'</pre>
<p>しかし、下記の例は、アローの後に改行を入れたり、括弧を使って、更に引数の内側で改行を使うことで、綺麗で柔らかなコードに修正できることを確認しています。引数の途中に改行を入れることもできます。</p>
<pre class="brush: js notranslate">var func = (a, b, c) =>
1;
var func = (a, b, c) => (
1
);
var func = (a, b, c) => {
return 1
};
var func = (
a,
b,
c
) => 1;
// no SyntaxError thrown</pre>
<h2 id="Parsing_order" name="Parsing_order">解析の順序</h2>
<p>アロー関数内のアロー(矢印)はオペレーターではないですが、アロー関数は通常の関数と異なり、<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Operator_Precedence">オペレーターを引き継いだ</a>特別な解析ルールを持ちます。</p>
<pre class="brush: js notranslate">let callback;
callback = callback || function() {}; // ok
callback = callback || () => {};
// SyntaxError: invalid arrow-function arguments
callback = callback || (() => {}); // ok
</pre>
<h2 id="More_examples" name="More_examples">さらなる例</h2>
<pre class="brush: js line-numbers language-js notranslate">// 空のアロー関数は undefined を返します
let empty = () => {};
(() => 'foobar')();
// "foobar" を返します
// (this is an <a href="https://wiki.developer.mozilla.org/ja/docs/Glossary/IIFE">Immediately Invoked Function Expression</a>)
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 => {
// ...
});
// 見た目に解析が簡単な引数なしのアロー関数
setTimeout( () => {
console.log('I happen sooner');
setTimeout( () => {
// deeper code
console.log('I happen later');
}, 1);
}, 1);
</pre>
<h2 id="Specifications" name="Specifications">仕様</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">仕様書</th>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}}</td>
</tr>
</tbody>
</table>
<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの実装状況</h2>
<div>
<div class="hidden">この互換性テーブルは自動生成された物です。編集する必要がある場合は <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> へ Pull Request を送ってください。</div>
<p>{{Compat("javascript.functions.arrow_functions")}}</p>
</div>
<h2 id="See_also" name="See_also">関連項目</h2>
<ul>
<li><a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">hacks.mozilla.org サイトの "ES6 In Depth: Arrow functions"</a></li>
</ul>
|