JS関数の呼び出し、適用、バインドの超詳細な方法

JS関数の呼び出し、適用、バインドの超詳細な方法

JS 関数呼び出し、適用、バインドメソッド

1. call() メソッド

call()メソッドを呼び出すと、ターゲット関数がすぐに実行され、関数内のthisの参照が変更されます。これはメソッドの最初のパラメータを指し、 1 つずつリストされたパラメータは、ターゲット関数のパラメータとして 1 つずつ渡されます。

/* 通常モード */

obj = {
  合計(a, b) {
    console.log(これ)
    a + bを返す
  }
}

// sum 関数の apply メソッドと bind メソッドを実行します。出力される内容は以下のようになります。obj.sum.call() // ウィンドウを印刷
obj.sum.call(undefined, 1, 2) // 印刷ウィンドウ
obj.sum.call(null, 1, 2) // 印刷ウィンドウ

/* 厳密モード */
「厳密な使用」

// sum関数のapplyメソッドとbindメソッドを実行し、以下のように出力します。obj.sum.call() // undefinedを出力します。
obj.sum.call(undefined, 1, 2) // undefined と表示される
obj.sum.call(null, 1, 2) // null を出力します

1. call() メソッドのシミュレーション実装

要点:

  • myCall()メソッドが Function プロトタイプ オブジェクトに追加されます。ターゲット関数がこのメソッドを呼び出すと、myCall() メソッド内の this がターゲット関数を指します。
  • ターゲット関数をコンテキスト オブジェクトのメソッドとして実行し、ターゲット関数内の this がコンテキスト オブジェクトを指すようにします。
  • コンテキストオブジェクトからターゲット関数を削除します
  • スプレッド演算子...を使用して、ターゲット関数に渡されたパラメータを処理します。

call()、apply()、bind() メソッドのシミュレーション実装では、最初のパラメータが渡されないか、undefined または null が渡された場合、ここでは JS 通常モードと厳密モードで統一された処理が行われ、つまり、対象関数内の this は window オブジェクトを指します。

コードは次のとおりです。

Function.prototype.myCall = function (コンテキスト、...引数) {
  コンテキスト === 未定義 || コンテキスト === null の場合 {
    コンテキスト = ウィンドウ
  }
  // 次の行はコアコードです context.fn = this
  const 結果 = context.fn(...args)
  コンテキストを削除する.fn
  結果を返す
}

obj1 = {
  基本数: 1,
  合計(a, b) {
    console.log(これ)
    this.basicNum + a + b を返す
  }
}
obj2 = {
  基本数: 9
}
コンソールログ(obj1.sum.call(obj2, 2, 3)) // 14
コンソールログ(obj1.sum.myCall(obj2, 2, 3)) // 14

2. apply() メソッド

apply()メソッドを呼び出すと、ターゲット関数が直ちに実行され、関数内のthisの参照が変更されます。これはメソッドの最初のパラメータを指します。2 番目のパラメータは、パラメータ配列または引数オブジェクトです。各配列要素または引数オブジェクトによって表される各パラメータは、ターゲット関数のパラメータとして 1 つずつ渡されます。

1. apply() メソッドのシミュレーション実装

要点:

  • myApply()メソッドが Function プロトタイプ オブジェクトに追加されます。ターゲット関数がこのメソッドを呼び出すと、myApply() メソッド内の this がターゲット関数を指します。
  • ターゲット関数をコンテキスト オブジェクトのメソッドとして実行し、ターゲット関数内の this がコンテキスト オブジェクトを指すようにします。
  • コンテキストオブジェクトからターゲット関数を削除します
  • スプレッド演算子...を使用して、ターゲット関数に渡されたパラメータを処理します。

コードは次のとおりです。

Function.prototype.myApply = 関数 (コンテキスト、引数) {
  コンテキスト === 未定義 || コンテキスト === null の場合 {
    コンテキスト = ウィンドウ
  }
  // 次の行はコアコードです context.fn = this
  const 結果 = context.fn(...args)
  コンテキストを削除する.fn
  結果を返す
}

コンソール.log(obj1.sum.apply(obj2, [2, 3])) // 14
コンソール.log(obj1.sum.myApply(obj2, [2, 3])) // 14

3. bind() メソッド

  • bind()メソッドを呼び出すと、新しい関数 (ターゲット関数のコピー) が返されます。関数内のthisメソッドの最初のパラメータを指し、1 つずつリストされたパラメータは、ターゲット関数のパラメータとして 1 つずつ渡されます。その後に新しい関数を実行することは、ターゲット関数を実行することと同じです。
  • bind()メソッドは関数のカリー化を実装しているため、ターゲット関数にパラメータを 2 回渡すことができます。最初のパラメータは bind() メソッドの最初のパラメータの後にリストされ、2 番目のパラメータは新しい関数にリストされます。

1. bind() メソッドのシミュレーション実装

要点:

  • myBind()メソッドが Function プロトタイプ オブジェクトに追加されます。ターゲット関数がこのメソッドを呼び出すと、myBind() メソッド内の this がターゲット関数を指します。
  • ターゲット関数をコンテキスト オブジェクトのメソッドとして実行し、ターゲット関数内の this がコンテキスト オブジェクトを指すようにします。
  • コンテキストオブジェクトからターゲット関数を削除します
  • スプレッド演算子...を使用して、ターゲット関数に渡される最初のパラメータと後続のパラメータを処理します。

コードは次のとおりです。

Function.prototype.myBind = function (context, ...initArgs) {
  コンテキスト === 未定義 || コンテキスト === null の場合 {
    コンテキスト = ウィンドウ
  }
  // この値をキャッシュする const _this = this
  関数を返す (...引数) {
    // 次の行はコアコードです context.fn = _this
    const 結果 = context.fn(...initArgs, ...args)
    コンテキストを削除する.fn
    結果を返す
  }
}

コンソール.log(obj1.sum.bind(obj2, 2)(3)) // 14
コンソール.log(obj1.sum.myBind(obj2, 2)(3)) // 14

IV. 結論

3 つの方法の類似点と相違点:

類似点:
どちらも、ターゲット関数の実行時に内部 this ポイントを変更できます。メソッドの最初のパラメーターは、関数の実行時に内部 this 値を指定するために使用されます。ターゲット関数に任意の数のパラメーターを渡すことがサポートされています。メソッドの最初のパラメーターに値が渡されないか、undefined または null が渡された場合、JavaScript の通常モードでは、ターゲット関数内の this は window オブジェクトを指し、厳密モードでは、それぞれ undefined または null を指します。

違い:
apply() メソッドは 2 つのパラメータを受け入れますが、call() メソッドと bind() メソッドは複数のパラメータを受け入れます。
apply() メソッドがターゲット関数にパラメータを渡す場合、メソッドの 2 番目のパラメータとしてパラメータ配列または引数オブジェクトを渡すだけで済みますが、call() メソッドと bind() メソッドでは、メソッドのパラメータの後にパラメータを 1 つずつリストする必要があります。
call() メソッドと apply() メソッドが呼び出されると、ターゲット関数はすぐに実行されますが、bind() メソッドは実行されません。bind() メソッドは、ターゲット関数のコピーである新しい関数を返します。関数内の this は、bind() メソッドの最初のパラメータを指します。その後に新しい関数を実行することは、ターゲット関数を実行することと同じです。
bind() メソッドのみが関数カリー化を実装しているため、ターゲット関数にパラメータを 2 回渡すことができます。

上記は、JS 関数の呼び出し、適用、バインドの超詳細なメソッドの詳細です。JS 関数の呼び出し、適用、バインドメソッドの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • JavaScript 関数型プログラミングの基礎
  • JS関数の継承について学ぶ記事
  • JavaScript 基礎シリーズ: 関数とメソッド
  • JavaScript 関数呼び出し、適用、バインド メソッドのケース スタディ
  • JavaScript の矢印関数と通常の関数の違いの詳細な説明
  • JavaScript の知識: コンストラクタも関数である
  • JavaScriptのスリープ関数の使用
  • JavaScript における変数と関数の昇格の詳細な例
  • JavaScript の 50 以上のユーティリティ関数の概要
  • 集める価値のある 15 個の JavaScript 関数

<<:  よく使われるLinuxコマンド「ll」が無効、またはコマンドが見つからないという問題を解決します

>>:  MySQL のスロークエリの方法と例

推薦する

Win7 インストール MySQL 5.6 チュートリアル図

目次1. ダウンロード2. インストール3. my.ini ファイルを設定する(デフォルトのエンコー...

ワンクリックで雨や雪のエフェクトを実現する ThingJS パーティクルエフェクト

目次1. パーティクルエフェクト2. シーンを読み込む3. さまざまな粒子効果の実現エンディング: ...

W3C チュートリアル (13): W3C WSDL アクティビティ

Web サービスは、アプリケーション間の通信に関係します。 WSDL は、XML ベースの Web ...

LayUI+Shiroは動的なメニューを実装し、メニュー拡張の例を記憶します

目次1. Maven 依存関係2. メニュー関連クラス1. メインメニュー2. サブメニュー3. S...

HTML H タイトルタグの使用

H タグ、特に h1 タグの使用は常に議論の的となっている問題であり、私たちが研究する価値のある問題...

Vueを使用して天気コンポーネントをロードする方法の詳細な説明

この記事では、Vueを使用して天気コンポーネントをロードする方法を参考までに紹介します。具体的な内容...

Nginx フォワードプロキシとリバースプロキシの違いと原理分析

1. フォワードプロキシとリバースプロキシの違いフォワード プロキシはクライアントのプロキシとして機...

JS関数の継承について学ぶ記事

目次1. はじめに: 2. プロトタイプチェーン継承: 3. コンストラクタ継承の借用(オブジェクト...

Portainer を使用した Docker コンテナのデプロイのプロジェクト実践

目次1. 背景2. 操作手順3. Portinerをインストールする3.1 Dockerのデプロイメ...

mysql5.6 マスタースレーブ設定と非同期の問題の詳細な説明

目次1. MySQL マスタースレーブレプリケーションの原理2. MySQLのコンパイルとインストー...

JS と Nodejs におけるイベント駆動型開発についての簡単な説明

目次イベント駆動型とパブリッシュ・サブスクライブ型ブラウザの JavaScript ではイベント駆動...

Zabbix 5.0 ディスク自動検出と読み取り/書き込み監視の問題を分析する

ディスクを自動的に検出する構成キーの値注: このキー値は Linux プラットフォームでのみサポート...

非常に実用的なMySQL関数の包括的な概要、詳細な例の分析チュートリアル

目次1. MySQLの関数の説明2. 単行関数の分類3. キャラクター機能4. 数学関数5. 日付と...

MySQL 8.0 再帰クエリの簡単な使用例

序文この記事では、MySQL 8.0 の新機能を使用して再帰クエリを実装します。詳細なサンプル コー...