MochiuWiki : SUSE, EC, PCB
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
JavaScriptの基礎 - アロー関数のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
JavaScriptの基礎 - アロー関数
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == アロー関数 (Arrow Function) は、ES2015 (ES6)で導入された関数定義の新しい構文である。<br> <code>=></code> 記号を使った簡潔な記法により、従来の <code>function</code> キーワードによる関数式をより短く記述できる。<br> <br> アロー関数の最大の特徴は、自身の <code>this</code> を持たない点である。<br> 通常の関数は呼び出し方によって <code>this</code> の値が変化するが、アロー関数は定義された場所 (レキシカルスコープ) の <code>this</code> を継承する。<br> <br> この特性により、コールバック関数内で <code>this</code> が予期せず変わるという従来の問題を自然に解決できる。<br> <br> また、単一の式を返す場合は中括弧とreturnキーワードを省略できる <code>暗黙return</code> (implicit return) の機能も持つ。<br> これにより、<code>map</code> や <code>filter</code> 等の配列メソッドと組み合わせた時に簡潔なコードを記述することができる。<br> <br> 一方で、アロー関数は全ての場面で通常の関数の代替として使えるわけではない。<br> オブジェクトメソッドの定義、コンストラクタとしての使用、<code>arguments</code> オブジェクトの参照が必要な場面ではアロー関数を使用できない。<br> <br> ReactをはじめとするモダンなJavaScriptフレームワークでは、コンポーネント定義、イベントハンドラ、配列メソッドとの組み合わせにおいてアロー関数が最頻出の関数定義形式となっている。<br> <u>アロー関数の構文、制約、通常関数との使い分けを正確に理解することは、現代的なJavaScript開発において必須の知識である。</u><br> <br><br> == 基本構文 == ==== 基本的な記法 ==== アロー関数の基本的な構文はブロック構文であり、通常の関数式に相当する。<br> 中括弧内に処理を記述し、値を返す場合は明示的にreturnを記述する。<br> <br> <syntaxhighlight lang="javascript"> // 基本的なブロック構文 (<引数1>, <引数2>) => { // 処理 return <戻り値>; } </syntaxhighlight> <br> 通常の関数式とアロー関数の対比を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> // 通常の関数式 const add = function(a, b) { return a + b; }; // アロー関数 (ブロック構文) const addArrow = (a, b) => { return a + b; }; console.log(add(3, 5)); // 8 console.log(addArrow(3, 5)); // 8 </syntaxhighlight> <br> 複数の処理が必要な場合は、ブロック構文を使用する。<br> <br> <syntaxhighlight lang="javascript"> const greet = (name) => { const message = "こんにちは、" + name + "さん"; console.log(message); return message; }; greet("Alice"); // "こんにちは、Aliceさん" </syntaxhighlight> <br> ==== 引数の省略記法 ==== アロー関数では、引数の数に応じて括弧を省略できる場合がある。<br> <br> 引数が1つの場合、括弧を省略することができる。<br> <br> <syntaxhighlight lang="javascript"> // 引数が1つ: () を省略可能 const double = x => { return x * 2; }; // 括弧あり (どちらでも動作する) const doubleWithParens = (x) => { return x * 2; }; console.log(double(5)); // 10 console.log(doubleWithParens(5)); // 10 </syntaxhighlight> <br> 引数が0個の場合、括弧は省略できず必須である。<br> <br> <syntaxhighlight lang="javascript"> // 引数が0個: () は必須 const sayHello = () => { return "Hello!"; }; console.log(sayHello()); // "Hello!" </syntaxhighlight> <br> 引数が複数の場合、括弧は必須である。<br> <br> <syntaxhighlight lang="javascript"> // 引数が複数: () は必須 const multiply = (a, b) => { return a * b; }; const sum3 = (a, b, c) => { return a + b + c; }; console.log(multiply(4, 5)); // 20 console.log(sum3(1, 2, 3)); // 6 </syntaxhighlight> <br><br> == 省略記法 == ==== 単一式の暗黙return ==== アロー関数では、関数本体が単一の式である場合に中括弧とreturnキーワードを省略できる。<br> 式の評価結果が自動的に戻り値となる。<br> これを、<code>暗黙return</code> (implicit return) と呼ぶ。<br> <br> <syntaxhighlight lang="javascript"> // ブロック構文 (明示的 return) const add = (a, b) => { return a + b; }; // 式本体 (暗黙 return) const addShort = (a, b) => a + b; console.log(add(3, 4)); // 7 console.log(addShort(3, 4)); // 7 </syntaxhighlight> <br> <code>暗黙return</code> が使えるのは式のみであり、<code>if</code> 文や <code>for</code> 文等の文は使用できない。<br> <br> <syntaxhighlight lang="javascript"> // 式: 暗黙returnが使用できる const isEven = n => n % 2 === 0; const getName = user => user.name; console.log(isEven(4)); // true console.log(isEven(3)); // false </syntaxhighlight> <br> 配列の <code>map</code> や <code>filter</code> との組み合わせで、<code>暗黙return</code> の効果が際立つ。<br> <br> <syntaxhighlight lang="javascript"> const numbers = [1, 2, 3, 4, 5]; // 通常の関数式 const doubled1 = numbers.map(function(n) { return n * 2; }); // アロー関数 (暗黙 return) const doubled2 = numbers.map(n => n * 2); // filter との組み合わせ const evens = numbers.filter(n => n % 2 === 0); console.log(doubled2); // [2, 4, 6, 8, 10] console.log(evens); // [2, 4] </syntaxhighlight> <br> ==== オブジェクトリテラルの返却 ==== アロー関数で <code>暗黙return</code> を使用してオブジェクトリテラルを返す場合は、括弧で囲む必要がある。<br> 中括弧 <code>{}</code> はブロックとして解釈されるため、そのまま記述するとエラーとなる。<br> <br> <syntaxhighlight lang="javascript"> // 正しい書き方: () で囲んでオブジェクトリテラルとして扱う const getUser2 = (name, age) => ({ name: name, age: age }); // 誤った書き方: {} がブロックと解釈され、undefined が返る const getUser1 = (name, age) => { name: name, age: age }; // SyntaxError または undefined // プロパティ短縮記法との組み合わせ const getUser3 = (name, age) => ({ name, age }); console.log(getUser2("Alice", 30)); // { name: "Alice", age: 30 } console.log(getUser3("Bob", 25)); // { name: "Bob", age: 25 } </syntaxhighlight> <br> 配列メソッドでオブジェクトを返す時の例を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> const users = ["Alice", "Bob", "Charlie"]; // 正: () で囲む const result2 = users.map(name => ({ id: name.length, name: name })); // 誤: {} がブロックとして解釈される // const result1 = users.map(name => { id: name.length, name: name }); console.log(result2); // [ // { id: 5, name: "Alice" }, // { id: 3, name: "Bob" }, // { id: 7, name: "Charlie" } // ] </syntaxhighlight> <br> ==== 省略記法の使い分け ==== ブロック構文と式本体のどちらを使うかは、処理の内容と可読性を基準に判断する。<br> <br> <center> {| class="wikitable" |+ アロー関数の構文選択基準 ! 構文 !! 使用場面 |- | 式本体 (暗黙 return) || 単一の式を評価して返すだけの処理<br><code>map</code>、<code>filter</code>、<code>find</code> 等の配列メソッドのコールバック<br>シンプルな変換処理や条件式 |- | ブロック構文 || 複数の処理ステップが必要な場合<br>変数への代入や条件分岐が必要な場合<br><code>console.log</code> 等の副作用を伴う処理 |} </center> <br> <syntaxhighlight lang="javascript"> // 式本体が適切な場面 (シンプルな変換) const prices = [100, 200, 300]; const taxIncluded = prices.map(price => price * 1.1); const expensive = prices.filter(price => price >= 200); // ブロック構文が適切な場面 (複数の処理) const formatPrice = (price) => { const taxed = Math.floor(price * 1.1); return taxed.toLocaleString() + "円"; }; console.log(taxIncluded); // [110, 220, 330] console.log(formatPrice(1000)); // "1,100円" </syntaxhighlight> <br><br> == thisを束縛しない特性 == ==== レキシカルthis ==== アロー関数は自身の <code>this</code> を作成しない。<br> 代わりに、アロー関数が定義された場所 (レキシカルスコープ) の <code>this</code> を継承して使用する。<br> <br> この特性を、<u>レキシカルthis</u>と呼ぶ。<br> <br> <syntaxhighlight lang="javascript"> const obj = { name: "Alice", // 通常のメソッド: thisはobjを参照 greet: function() { console.log("Hello, " + this.name); // "Hello, Alice" }, // アロー関数はレキシカルthisを継承する // (このケースでは外側のthisを参照) }; </syntaxhighlight> <br> アロー関数内の <code>this</code> は、関数が定義された時点で確定し、呼び出し方によって変化しない。<br> <br> ==== 通常関数でのthis問題 ==== 通常の関数では、<code>this</code> の値は呼び出し方によって動的に決まる。<br> メソッド内でコールバック関数や <code>setTimeout</code> を使用する時に、<code>this</code> が予期せずグローバルオブジェクト (または、undefined) になるという問題が発生する。<br> <br> <syntaxhighlight lang="javascript"> function Timer() { this.count = 0; // 問題のあるコード: 通常関数のコールバック setTimeout(function() { this.count++; // this は window または undefined console.log(this.count); // NaN または TypeError }, 300); } const timer = new Timer(); </syntaxhighlight> <br> ES2015以前は、この問題を解決するために以下の2つのパターンが広く使用されていた。<br> <br> <syntaxhighlight lang="javascript"> // パターン1: self = this パターン function Timer1() { this.count = 0; const self = this; // thisを変数に保存 setTimeout(function() { self.count++; // selfを通じてアクセス console.log(self.count); // 1 }, 300); } // パターン2: .bind(this) メソッド function Timer2() { this.count = 0; setTimeout(function() { this.count++; console.log(this.count); // 1 }.bind(this), 300); // thisをバインド } </syntaxhighlight> <br> ==== アロー関数による解決 ==== アロー関数を使用すると、<code>this</code> の問題を自然かつ簡潔に解決できる。<br> アロー関数は外側の <code>this</code> (この場合、<code>Timer</code> インスタンス) を継承するため、追加の工夫が不要である。<br> <br> <syntaxhighlight lang="javascript"> function Timer() { this.count = 0; // アロー関数: 外側の this を継承する setTimeout(() => { this.count++; // this は Timer インスタンスを参照 console.log(this.count); // 1 }, 300); } const timer = new Timer(); </syntaxhighlight> <br> メソッド内のコールバックでも同様に <code>this</code> が保持される。<br> <br> <syntaxhighlight lang="javascript"> const counter = { count: 0, items: [1, 2, 3], // アロー関数コールバック: thisがcounterを参照 increment: function() { this.items.forEach(item => { this.count += item; // this は counter を参照 }); console.log(this.count); // 6 } }; counter.increment(); </syntaxhighlight> <br><br> == アロー関数の制約 == ==== 使用できない場面 ==== <u>アロー関数には、通常の関数と異なる制約があり、以下の場面では使用できない または 使用すべきでない。</u><br> <br> <center> {| class="wikitable" |+ アロー関数の使用制約 ! 制約事項 !! 説明 |- | オブジェクトメソッドの定義 || アロー関数の <code>this</code> はオブジェクト自身を参照しない。<br>メソッドには通常の関数定義またはメソッド短縮記法を使用する。 |- | コンストラクタとしての使用 || <code>new</code> キーワードでアロー関数を呼び出すと <u>TypeError</u> が発生する。 |- | argumentsオブジェクトの参照 || アロー関数は <code>arguments</code> オブジェクトを持たない。<br>可変長引数が必要な場合は残余引数 <code>(...args)</code> を使用する。 |- | 動的thisが必要な場面 || <code>addEventListener</code> 等でコールバックの <code>this</code> をイベントターゲットにする場合はアロー関数は不適切 |} </center> <br> ==== 各制約のコード例 ==== オブジェクトメソッドでの制約を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> const person = { name: "Alice", // 正: 通常のメソッド定義 greetFunction: function() { console.log("Hello, " + this.name); // "Hello, Alice" }, // 正: メソッド短縮記法 (推奨) greetShorthand() { console.log("Hello, " + this.name); // "Hello, Alice" } // 誤: アロー関数のthisはグローバルを参照 greetArrow: () => { console.log("Hello, " + this.name); // undefined (グローバル) }, }; person.greetArrow(); // "Hello, undefined" person.greetFunction(); // "Hello, Alice" person.greetShorthand(); // "Hello, Alice" </syntaxhighlight> <br> コンストラクタとしての制約を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> // 通常の関数: コンストラクタとして使用できる function RegularFunction(name) { this.name = name; } const obj1 = new RegularFunction("Alice"); // OK // アロー関数: コンストラクタとして使用できない const ArrowFunction = (name) => { this.name = name; }; const obj2 = new ArrowFunction("Bob"); // TypeError: ArrowFunction is not a constructor </syntaxhighlight> <br> <code>arguments</code> オブジェクトの制約を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> // 通常の関数: arguments オブジェクトを持つ function regularSum() { let total = 0; for (let i = 0; i < arguments.length; i++) { total += arguments[i]; } return total; } // アロー関数: arguments は使用できない const arrowSum = () => { // console.log(arguments); // ReferenceError: arguments is not defined }; // アロー関数での代替: 残余引数を使用 const arrowSumFixed = (...args) => { return args.reduce((total, n) => total + n, 0); }; console.log(regularSum(1, 2, 3)); // 6 console.log(arrowSumFixed(1, 2, 3)); // 6 </syntaxhighlight> <br> <code>addEventListener</code> での制約を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> const button = document.querySelector("button"); // 正: 通常の関数でthisをイベントターゲットとして使用 button.addEventListener("click", function() { console.log(this); // ボタン要素 (押下された要素) this.classList.add("clicked"); // OK }); // 誤: アロー関数のthisは外側のスコープを参照 button.addEventListener("click", () => { console.log(this); // window (外側のthis) // this.classList.add("clicked"); // エラーの可能性 }); </syntaxhighlight> <br><br> == 通常関数との比較 == 下表に、アロー関数と通常関数の主な違いを示す。<br> <br> <center> {| class="wikitable" |+ アロー関数と通常関数の比較 ! 特性 !! アロー関数 !! 通常関数 |- | this || レキシカル (定義場所のthisを継承) || 呼び出し方に依存して動的に変化 |- | arguments || なし (残余引数 <code>(...args)</code> を使用) || あり |- | new可否 || 不可 (TypeError) || 可能 |- | ホイスティング || なし (変数のルールに従う) || 関数宣言のみあり |- | prototype || なし || あり |- | 構文 || <code>() => {}</code> || <code>function() {}</code> |- | メソッド定義 || 非推奨 (thisの問題) || 推奨 |} </center> <br><br> == Reactでの使用場面 == ==== コンポーネント定義 ==== Reactでは、関数コンポーネントをアロー関数で定義することが一般的なパターンである。<br> <br> <syntaxhighlight lang="javascript"> import React, { useState } from "react"; // アロー関数によるコンポーネント定義 const App = () => { return <h1>Hello, World!</h1>; }; // propsを受け取るコンポーネント const Greeting = ({ name }) => { return <h2>こんにちは、{name}さん</h2>; }; // 暗黙returnを使用した簡潔な記法 (JSXを括弧で囲む) const SimpleButton = ({ label }) => ( <button>{label}</button> ); export default App; </syntaxhighlight> <br> ==== イベントハンドラ ==== Reactのイベントハンドラとして、アロー関数はインラインで記述することが多い。<br> アロー関数を使用することにより、外側の <code>this</code> (クラスコンポーネントの場合) や スコープ内の変数に自然にアクセスできる。<br> <br> <syntaxhighlight lang="javascript"> import React, { useState } from "react"; const Counter = () => { const [count, setCount] = useState(0); // アロー関数でイベントハンドラを定義 const handleIncrement = () => { setCount(count + 1); }; return ( <div> <p>カウント: {count}</p> {/* インラインのアロー関数 */} <button onClick={() => setCount(count + 1)}>+1</button> {/* ハンドラ関数を渡す (関数を渡すのであって、呼び出さない) */} <button onClick={handleIncrement}>+1 (ハンドラ使用)</button> {/* 誤: () をつけると即時呼び出しになる */} {/* <button onClick={handleIncrement()}>+1</button> */} </div> ); }; </syntaxhighlight> <br> <u>イベントハンドラでは、関数を渡す時に <code>()</code> を不可しないことが重要である。</u><br> <u><code>onClick={handleClick}</code> は関数の参照を渡すが、<code>onClick={handleClick()}</code> はレンダリング時に即座に関数を呼び出してしまう。</u><br> <br> ==== 配列メソッドとの組み合わせ ==== Reactでデータをリストとして表示する時、<code>map</code> と アロー関数の組み合わせが頻繁に使用される。<br> <br> <syntaxhighlight lang="javascript"> import React from "react"; const ItemList = ({ items }) => { return ( <ul> {/* map とアロー関数でリスト要素を生成 */} {items.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> ); }; const FilteredList = ({ items }) => { // filter と map を組み合わせてアクティブな項目のみ表示 const activeItems = items .filter(item => item.isActive) .map(item => ( <li key={item.id}>{item.name}</li> )); return <ul>{activeItems}</ul>; }; // 使用例 const sampleItems = [ { id: 1, name: "リンゴ", isActive: true }, { id: 2, name: "バナナ", isActive: false }, { id: 3, name: "チェリー", isActive: true } ]; </syntaxhighlight> <br><br> == 関連情報 == * [[JavaScriptの基礎 - 関数宣言と関数式]] *: 関数宣言と関数式、デフォルト引数、残余引数 * [[JavaScriptの基礎 - 変数宣言]] *: let / const / varの宣言方法、スコープ、ホイスティング * [[JavaScriptの基礎 - クロージャ]] *: レキシカルスコープ、クロージャの仕組みと実用例 * [[JavaScriptの基礎 - コールバック関数]] *: コールバック関数、高階関数、タイマ、イベントリスナー <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:Web]]
JavaScriptの基礎 - アロー関数
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse