diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/ja/web/javascript/reference/functions/arrow_functions | |
parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
download | translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2 translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip |
initial commit
Diffstat (limited to 'files/ja/web/javascript/reference/functions/arrow_functions')
-rw-r--r-- | files/ja/web/javascript/reference/functions/arrow_functions/index.html | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/files/ja/web/javascript/reference/functions/arrow_functions/index.html b/files/ja/web/javascript/reference/functions/arrow_functions/index.html new file mode 100644 index 0000000000..b178700bd9 --- /dev/null +++ b/files/ja/web/javascript/reference/functions/arrow_functions/index.html @@ -0,0 +1,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> |