call()、apply()、bind() メソッドを学習することは、JavaScript でこのコンテキストを制御できるため重要です。あるオブジェクトから別のオブジェクトにメソッドを借用する場合や、コールバック内で正しいコンテキストを維持する場合など、デフォルトのこの動作が期待どおりに動作しない状況では、これらのメソッドは柔軟性と制御を提供します。これらをマスターすることで、より効率的で再利用可能でコンテキストを認識した関数を作成できるようになり、複雑なアプリケーションで特に役立ちます。
call()、apply()、bind() メソッドに入る前に、「this」キーワードとそのメカニズムを理解しましょう。
次の箇条書きで、このキーワードがいつ、何を指すのかを理解しましょう:
オブジェクト メソッドでは、 はオブジェクトを指します。オブジェクト内で定義されたメソッド内では、メソッドを所有するオブジェクトを指します。
通常の関数では、 これはグローバル オブジェクトを指します。非厳密モードでは、関数が (オブジェクトのメソッドとしてではなく) グローバル コンテキストで呼び出された場合、これはグローバル オブジェクト (ブラウザーのウィンドウ) を参照します。
厳密モード関数では、 これは未定義です。関数がオブジェクトのメソッドではなく、特定のコンテキスト (呼び出し、適用、またはバインド経由) にバインドされていない場合、これは厳密モードでは未定義になります。
イベント ハンドラーでは、 これはイベントを受信した要素を指します。イベントがトリガーされると、これはイベントを呼び出した HTML 要素を参照します。
<button onclick="this.style.display='none'"> Click to Remove Me! </button>
この場合、これは onclick イベントを受け取ったボタン要素自体を指します。
アロー関数では、 動作が異なります。アロー関数には独自の this コンテキストがありません。代わりに、これはアロー関数の作成時に周囲のスコープから字句的に継承されます。これは、アロー関数内の this が、それを囲んでいる関数またはコンテキストの this 値を参照することを意味します。
const person = { name: "Alice", greet: function() { setTimeout(() => { console.log(`Hi, I'm ${this.name}`); }, 1000); } }; person.greet(); // Output: Hi, I'm Alice
この場合、setTimeout 内のアロー関数は、person オブジェクトを指す挨拶メソッドからこれを継承します。
call() メソッドを使用すると、あるオブジェクトから関数またはメソッドを「借用」し、他のオブジェクトを最初の引数として渡すことで、それを別のオブジェクトで使用できます。最初の引数は関数内の this 値になり、その後に追加の引数が続きます。
call() メソッドは新しい関数を作成しません。指定されたコンテキストと引数を使用して既存の関数を実行します。
const person = { fullName: function(city, country) { console.log(this.firstName + " " + this.lastName + " is going to " + city + ", " + country + "."); } } const person1 = { firstName: "John", lastName: "Doe" } person.fullName.call(person1, "Oslo", "Norway"); // Output: John Doe is going to Oslo, Norway.
この例では、call() を使用して person1 のデータ (firstName と lastName) を使用して person の fullName メソッドを実行し、追加の引数は「Oslo」と「Norway」です。
apply() メソッドは call() メソッドと非常に似ています。主な違いは、引数が関数に渡される方法にあります。 apply() を使用すると、引数を個別に渡すのではなく、配列 (または配列のようなオブジェクト) として渡します。
call() と同様に、apply() メソッドは新しい関数を作成しません。指定されたコンテキスト (この値) と引数を使用して関数がすぐに実行されます。
const person = { fullName: function(city, country) { console.log(this.firstName + " " + this.lastName + " is going to " + city + ", " + country + "."); } } const person1 = { firstName: "John", lastName: "Doe" } person.fullName.apply(person1, ["Oslo", "Norway"]); // Output: John Doe is going to Oslo, Norway.
この例では、apply() を使用して person オブジェクトの fullName メソッドを呼び出しますが、そのコンテキスト (this) は person1 です。引数「オスロ」と「ノルウェー」は配列として渡されます。
JavaScript の binding() メソッドを使用すると、call() や apply() と同様に、関数またはメソッドのコンテキスト (この値) を設定できます。ただし、call() や apply() とは異なり、bind() メソッドは関数をすぐに呼び出しません。代わりに、指定したオブジェクトに this 値が設定された新しい関数を返します。
const person = { fullName: function(city, country) { console.log(this.firstName + " " + this.lastName + " is going to " + city + ", " + country + "."); } } const person1 = { firstName: "John", lastName: "Doe" } const func = person.fullName.bind(person1); func("Oslo", "Norway"); // Output: John Doe is going to Oslo, Norway.
この例では、bind() は this 値を person1 に設定して新しい関数 func を作成します。この関数はすぐには呼び出されませんが、引数「Oslo」と「Norway」を渡して後で呼び出すことができます。
ここでは、call()、apply()、bind() を使用すると、特にロギング目的で関数の 部分的な適用 を処理する際に効率をもたらす、小さいながらも複雑なアプリケーションの例を示します。
アクションを実行するさまざまなユーザーに関する情報をログに記録する集中ログ機能があるとします。 binding() を使用すると、このコンテキストをさまざまなユーザーに効率的に設定でき、コードの繰り返しを回避できます。
const logger = { logAction: function(action) { console.log(`${this.name} (ID: ${this.id}) performed: ${action}`); } }; const user1 = { name: "Alice", id: 101 }; const user2 = { name: "Bob", id: 202 }; // Create new logger functions for different users const logForUser1 = logger.logAction.bind(user1); const logForUser2 = logger.logAction.bind(user2); // Perform actions without manually passing user context logForUser1("login"); // Output: Alice (ID: 101) performed: login logForUser2("purchase"); // Output: Bob (ID: 202) performed: purchase
コンテキストの再利用: アクションを記録するたびにユーザー コンテキストを手動で渡す必要はありません。コンテキスト (this) が一度バインドされると、ログは再利用可能でクリーンになります。
モジュール性: さらにユーザーやアクションを追加する必要がある場合は、関数自体を変更せずにそれらをロガーにすばやくバインドし、コードを DRY (Don'trepeat Yourself) に保つことができます。
以上がthis JavaScript のキーワード、call()、apply()、bind() メソッド - 簡単に説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。