概要長い年月を経て、ES6 は矢印関数やクラスなど、js の使いやすさを新たなレベルに引き上げました。これは素晴らしいことです。 アロー関数は最も価値のある新機能の 1 つであり、そのコンテキストの透明性と短い構文について説明した優れた記事が多数あります。 しかし、すべての取引には2つの側面があります。多くの場合、新しい機能は何らかの混乱をもたらしますが、その混乱の 1 つが矢印関数の誤った使用です。この記事では、矢印関数をバイパスして、古き良き関数式または新しい省略構文を使用する必要があるシナリオをいくつか説明します。また、コードの読みやすさに影響するため、コードを短くするように注意してください。 オブジェクトにメソッドを定義するJavaScript では、メソッドはオブジェクトのプロパティとして保存される関数です。メソッドが呼び出されると、this はメソッドが属するオブジェクトを参照します。 オブジェクトリテラルアロー関数は構文が短いので、メソッドの定義に使いたくなります。試してみましょう。 定数計算 = { 配列: [1, 2, 3], 合計: () => { console.log(this === window); // => true this.array.reduce((result, item) => result + item); を返します。 } }; console.log(this === window); // => true // "TypeError: undefined のプロパティ 'reduce' を読み取ることができません" をスローします 計算します。 calculate.sum メソッドは矢印関数を使用して定義されます。 しかし、呼び出されると、this.array が未定義であるため、calculate.sum() は TypeError をスローします。 calculate オブジェクトで sum() メソッドが呼び出されると、コンテキストは引き続き window になります。これは、矢印関数がコンテキストをウィンドウ オブジェクトに構文的にバインドするために発生します。 this.array を実行すると、window.array が実行されることになり、これは未定義になります。 解決策は、正規関数式を使用してメソッドを定義することです。これは呼び出し時に決定され、囲んでいるコンテキストによって決定されません。修正バージョンを見てみましょう。 定数計算 = { 配列: [1, 2, 3], 合計() { console.log(this === calculate); // => true this.array.reduce((result, item) => result + item); を返します。 } }; calculate.sum(); // => 6 sum は通常の関数なので、calculate.sum() を呼び出すと、これは calculate オブジェクトになります。 this.array は配列参照なので、要素の合計は正しく計算されます: 6。 オブジェクトプロトタイププロトタイプ オブジェクトでメソッドを定義する場合にも同じルールが適用されます。矢印関数を使用してsayCatNameメソッドを定義します。これはwindowを指します。 関数 MyCat(名前) { this.catName = 名前; } MyCat.prototype.sayCatName = () => { console.log(this === window); // => true this.catName を返します。 }; const cat = new MyCat('Mew'); cat.sayCatName(); // => 未定義 以前の方法を使用して関数式を定義します。 関数 MyCat(名前) { this.catName = 名前; } MyCat.prototype.sayCatName = 関数() { console.log(this === cat); // => true this.catName を返します。 }; const cat = new MyCat('Mew'); cat.sayCatName(); // => 'ニャー' sayCatName の通常関数は、メソッド cat.sayCatName() として呼び出されると、コンテキストを cat オブジェクトに変更します。 動的コンテキストコールバック関数これは、関数の呼び出し方法に応じてコンテキストを変更できる JS の強力な機能です。通常、コンテキストは呼び出しが行われるターゲット オブジェクトであり、これにより、このオブジェクトに何が起こるかと同じようにコードがより自然になります。 ただし、矢印関数は宣言時にコンテキストを静的にバインドし、動的にすることはできませんが、このアプローチには良い面と悪い面があり、動的バインドが必要になる場合があります。 DOM 要素にイベント リスナーをアタッチすることは、クライアント側プログラミングでは一般的なタスクです。イベントはハンドラー関数をトリガーし、これをターゲット要素として使用します。ここで矢印関数を使用するのは柔軟性が足りません。 次の例では、このようなハンドラーに矢印関数を使用しようとしています。 ボタン = document.getElementById('myButton'); button.addEventListener('click', () => { console.log(this === window); // => true this.innerhtml = 'ボタンをクリックしました'; }); グローバルコンテキストでは、これはウィンドウを指します。 クリック イベントが発生すると、ブラウザーはボタン コンテキストを使用してハンドラー関数を呼び出そうとしますが、矢印関数は定義済みのコンテキストを変更しません。 this.innerhtml は window.innerHTML と同等であり、意味がありません。 関数式を適用する必要があります。これにより、ターゲット要素に応じてこれを変更できます。 ボタン = document.getElementById('myButton'); button.addEventListener('click', 関数() { console.log(this === button); // => true this.innerHTML = 'クリックされたボタン'; }); ユーザーがボタンをクリックすると、ハンドラー関数内の this がボタンを指します。したがって、この質問です。 innerHTML = 'Clicked button' は、クリックされた状態を反映するようにボタンのテキストを正しく変更します。 コンストラクタの呼び出しコンストラクター呼び出し内の this は新しく作成されたオブジェクトです。 new MyFunction() が実行されると、コンストラクター MyFunction のコンテキストは新しいオブジェクトになります: this instanceof MyFunction === true。 矢印関数はコンストラクターとして使用できないことに注意してください。 JavaScript は例外をスローすることでこれを暗黙的に防止します。 いずれにしても、これは新しく作成されたオブジェクトではなく、囲むコンテキストから設定されます。つまり、矢印関数のコンストラクター呼び出しは意味をなさず、曖昧です。 これを実行すると何が起こるか見てみましょう: const メッセージ = (テキスト) => { this.text = テキスト; }; // "TypeError: メッセージはコンストラクタではありません" をスローします const helloMessage = 新しいメッセージ('Hello World!'); Message が矢印関数である new Message('Hello World!') を実行すると、Message はコンストラクターとして使用できないため、JavaScript は TypeError エラーをスローします。 上記の例は、関数式を使用して修正できます。これは、コンストラクターを作成する正しい方法です (関数宣言を含む)。 const メッセージ = 関数(テキスト) { this.text = テキスト; }; const helloMessage = 新しいメッセージ('Hello World!'); 省略構文矢印関数には、パラメータ括弧 ()、ブロック中括弧 {} を省略でき、関数本体にステートメントが 1 つしかない場合は return できるという優れた特性があります。これは非常に短い関数を書くのに役立ちます。 原作者の大学のプログラミング教授は学生たちに、C 言語で文字列の長さを計算する最短の関数を書くという興味深い課題を与えました。これは新しい言語を学び、探求する素晴らしい方法です。 しかし、実際のアプリケーションでは、多くの開発者がコードを読みます。 最も短い構文は、メソッドが何を行うかを同僚が即座に理解するのに必ずしも適切であるとは限りません。 ある時点で、ショートカット関数は読みにくくなるため、過度に使用しないようにしてください。例を挙げてみましょう。 const multiply = (a, b) => b === 未定義 ? b => a * b : a * b; 定数倍 = 乗算(2); ダブル(3); // => 6 乗算(2, 3); // => 6 multiply は、2 つの数値を乗算した結果、または後続の乗算演算のために最初の引数にバインドされたクロージャを返します。 機能は問題なく動作し、短いようです。しかし、最初からそれが何をするのか理解するのは困難でした。 読みやすくするために、矢印関数からオプションの中括弧と return ステートメントを復元するか、通常の関数を使用します。 関数 multiply(a, b) { b === 未定義の場合{ 関数(b)を返す{ a * b を返します。 } } a * b を返します。 } 定数倍 = 乗算(2); ダブル(3); // => 6 乗算(2, 3); // => 6 簡潔さと冗長性のバランスを見つけてコードをより直感的にすることが大切です。 要約する矢印関数が素晴らしい追加機能であることは間違いありません。正しく使用すると、.bind() の使用や、以前は必要だった場所でのコンテキストのキャプチャが簡単になります。また、コードも簡素化されます。 ある状況では利点となるものが、他の状況では欠点となることもあります。 矢印関数は、動的なコンテキストが必要な場合には使用できません。たとえば、メソッドの定義、コンストラクターを使用したオブジェクトの作成、イベントの処理時に this からターゲットを取得する場合などです。 以上がJSがアロー関数に適さない理由の詳細です。JSについてさらに詳しく知りたい方は、123WORDPRESS.COM内の他の関連記事もぜひご覧ください! 以下もご興味があるかもしれません:
|
<<: CentOS 7 で MySQL 5.7 をインストールして設定する
>>: Linuxコマンドのファイル上書きとファイル追加の詳細な説明
目次1. データベースを操作する1.1 データベースを作成する1.2 データベースをクエリする1.3...
この記事の例では、タイマー機能を実装するためのVueの具体的なコードを参考までに共有しています。具体...
この記事の例では、カウントダウン効果を実現するためのJavaScriptの具体的なコードを参考までに...
最近、本番環境のデータベースがログデータを狂ったように書き込み、主キー値のオーバーフローを引き起こし...
1.サービスコマンドサービスコマンドは実際には/etc/init.dディレクトリに移動し、関連プログ...
目次1. ブラウザのクッキーの値を取得する2. RGBを16進数に変換する3. クリップボードにコピ...
まず Linux に ssh をインストールします。例として Centos を使用します。ポータル:...
この記事では、例を使用して、MYSQL データベース テーブル構造を最適化する方法を説明します。ご参...
パフォーマンスの黄金律:エンドユーザーの応答時間のわずか 10% ~ 20% が HTML ドキュメ...
まず興味深い性質であるconic-gradientを紹介しましょう。円錐グラデーション!円グラフの作...
MySQL ストアド プロシージャ1. ストアドプロシージャ構文(フォーマット)を作成する 区切り文...
テーブルとは何ですか?テーブルは、データのキャリアである HTML テーブルです。以下は比較的標準的...
現在のページへのリンク。 -------------------一般的な使用法は次のとおりです。 &...
Docker 公式ドキュメントからの翻訳、原文: https://docs.docker.com/n...
Vue では、一般的にフロントエンドとバックエンドを分離したプロジェクトがあり、データ操作を実装する...