JS 矢印関数に適さないシナリオは何ですか?

JS 矢印関数に適さないシナリオは何ですか?

概要

長い年月を経て、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内の他の関連記事もぜひご覧ください!

以下もご興味があるかもしれません:
  • より良い JavaScript 条件文と一致条件を書くためのヒント (要約)
  • JSの矢印関数におけるこのポイントの詳細な説明
  • JavaScriptのアロー関数の特徴と通常の関数との違い
  • JavaScript の矢印関数と通常の関数の違いの詳細な説明
  • JavaScript で矢印関数を使用できないシナリオはどれですか
  • JavaScript の条件付きアクセス属性と矢印関数の紹介

<<:  CentOS 7 で MySQL 5.7 をインストールして設定する

>>:  Linuxコマンドのファイル上書きとファイル追加の詳細な説明

推薦する

MySQLの自動増分主キーの実装の詳細な説明

目次1. 自己増分値はどこに保存されますか? 2. 自己価値修正メカニズム3. 自動増分値を変更する...

React + Threejs + Swiper パノラマ効果を実現するための完全なコード

パノラマビュー効果を見てみましょう: 住所を表示スクリーンショット: 体験してみると、周囲の環境がぐ...

Ubuntu システムログで /var/log/messages を設定する方法

1. 問題の説明今日、システム ログ ファイルを確認する必要がありますが、/var/log/mess...

Mybatis mysqlの削除操作では、最初のデータメソッドのみを削除できます。

バグ図のように、削除文とパラメータをデータベースにコピーして実行し、2つのデータを削除しようとしたの...

VMware ESXi6.7 の簡単なセットアップ(画像とテキスト付き)

1. VMware vSphere の概要VMware vSphere は、業界をリードする最も信...

JSを段階的に学ぶ方法についての簡単な説明

目次概要1. jsの位置づけを明確に理解する2. 明確な学習パス3. 自己規律と粘り強さ4. 練習し...

Linux で MySQL パスワードを忘れた場合の解決策

問題は次のとおりです。mysql -uroot -p コマンドを入力しましたが、パスワードを忘れてし...

Angularの単一プロジェクトを複数プロジェクトにアップグレードするプロセス全体

目次序文開発環境新しいプロジェクトを作成するモバイルウェブプロジェクト角度付きJSONパブリックモジ...

Docker Compose ワンクリック ELK デプロイ方式の実装

インストールFilebeat は、より軽量でより安全なため、Logstash-Forwarder に...

docker-maven-pluginを使用してデプロイメントを自動化する方法を説明します

1. docker-maven-pluginの紹介私たちの継続的インテグレーションプロセスでは、プロ...

Vueは小さなメモ帳機能を実装しました

この記事の例では、メモ帳の小さな機能を実現するためのvueの具体的なコードを参考までに共有しています...

単一の Nginx IP アドレスに複数の SSL 証明書を設定する例

デフォルトでは、Nginx は IP アドレスごとに 1 つの SSL 証明書のみをサポートします。...

Vue3 スロットの使用状況の概要

目次1. Vスロットの紹介2. 匿名スロット3. 名前付きスロット4. スコープ付きスロット5. 動...

HTMLページ間でパラメータを渡すフロントエンド方式の詳細な説明

プロジェクトでよくある状況として、案件リストなどのリストが存在することがあります。リスト内の項目をク...