ホームページ > 記事 > ウェブフロントエンド > JS で 'this' ポインタを処理するいくつかの方法
私は、this
ポインターとも呼ばれる、JS の関数実行コンテキストのポインターを変更するのが好きです。
たとえば、配列のようなオブジェクトに対して配列メソッドを使用できます。
const reduce = Array.prototype.reduce; function sumArgs() { return reduce.call(arguments, (sum, value) => { return sum += value; }); } sumArgs(1, 2, 3); // => 6
一方、this
を理解するのは困難です。
私たちが使用している this
が間違っていることがよくあります。以下では、this
を目的の値に単純にバインドする方法を説明します。
始める前に、引数として指定された関数を単純に実行するヘルパー関数 execute(func)
が必要です。
function execute(func) { return func(); } execute(function() { return 10 }); // => 10
次に、this
を取り巻くエラーの本質、つまりメソッドの分離の理解に移ります。
1. メソッド分離の問題
フィールド firstName
と lastName# を含むクラス
Person があるとします。 ##。さらに、人のフルネームを返すメソッド
getFullName() があります。以下に示すように:
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = function() { this === agent; // => true return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智'
#person 関数がコンストラクターとして呼び出されていることがわかります:
new Person('front-end', 'Xiao Zhi') 。関数内の
this は、新しく作成されたインスタンスを表します。
getfullname()個人のフルネームを返します:
'フロントエンド Xiaozhi'。予想どおり、
getFullName() メソッド内の
this は
agent と同等です。
agent.getFullName メソッドを実行するとどうなるか:
execute(agent.getFullName); // => 'undefined undefined'実行結果が正しくありません:
'未定義 未定義'、これis
this 間違ったポインティングによって引き起こされる問題。
getFullName() メソッドの
this の値はグローバル オブジェクト (ブラウザ環境の
window) です。
this は
window,
${window.firstName} ${window.lastName} と等しくなります。実行結果は
'未定義 未定義' です。 。
execute(agent.getFullName) が呼び出されたときにメソッドがオブジェクトから切り離されるために発生します。基本的に、行われるのは単なる通常の関数呼び出しです (メソッド呼び出しではありません):
execute(agent.getFullName); // => 'undefined undefined' // 等价于: const getFullNameSeparated = agent.getFullName; execute(getFullNameSeparated); // => 'undefined undefined'これは、メソッドがオブジェクトから切り離されるときに呼び出されるものです。メソッドが切り離されて実行されると、
this 元のオブジェクトとの接続はありません。
this が正しいオブジェクトを指していることを確認するには、これを行う必要があります。
agent.getFullName()
を包含オブジェクトに静的にバインドします (アロー関数、
.bind() メソッドなどを使用)
this の不正なポインティングは、通常、次の状況で発生します。
Callback
// `methodHandler()`中的`this`是全局对象 setTimeout(object.handlerMethod, 1000);
イベント ハンドラーを設定するとき,
// React: `methodHandler()`中的`this`是全局对象 <button onClick={object.handlerMethod}> Click me </button>では、いくつかの便利なメソッド、つまりメソッドがオブジェクトから切り離されている場合に
this が目的のオブジェクトを指すようにする方法を紹介します。
2. コンテキストを閉じる
this がクラス インスタンスを指し続ける最も簡単な方法は、追加の変数
self を使用することです。 :
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; const self = this; this.getFullName = function() { self === agent; // => true return `${self.firstName} ${self.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
getFullName() は
self 変数を静的に閉じ、事実上手動で
this をバインドします。
execute(agent.getFullName) を呼び出すと、メソッド
this 内の
getFullName() が常に正しい値を指すため、すべてが正常に動作します。
3. アロー関数の使用
変数を追加せずにthis を静的にバインドする方法はありますか?はい、それがまさにアロー関数の機能です。
person:
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = () => `${this.firstName} ${this.lastName}`; } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'アロー関数は、
this を字句的にバインドします。簡単に言うと、定義されている外部関数
this の値を使用します。
4. バインディング コンテキスト
次に、さらに一歩進んで、ES6 のクラス リファクタリングPerson を使用しましょう。
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName() { return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => 'undefined undefined'残念ながら、新しいクラス構文を使用した場合でも、
execute(agent.getFullName) は依然として
"未定義 未定義" を返します。
self またはアロー関数を使用して
this が指すものを修正することは機能しません。
bind() メソッドに関連するトリックがあり、メソッドのコンテキストをコンストラクターにバインドします。
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = this.getFullName.bind(this); } getFullName() { return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
this in theconstructor です。 getFullName = this.getFullName.bind(this)メソッド
getFullName() をクラス インスタンスにバインドします。
execute(agent.getFullName) 期待どおりに動作し、
'frontend Xiaozhi' を返します。
5. ファットアローメソッド
#bind このメソッドは少し長すぎるため、ファットアローメソッドを使用できます:
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName = () => { return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
胖箭头方法getFullName =() =>{…}
绑定到类实例,即使将方法与其对象分离。
这种方法是在类中绑定this
的最有效和最简洁的方法。
6. 总结
与对象分离的方法会产生 this 指向不正确问题。静态地绑定this
,可以手动使用一个附加变量self
来保存正确的上下文对象。然而,更好的替代方法是使用箭头函数,其本质上是为了在词法上绑定this
。
在类中,可以使用bind()
方法手动绑定构造函数中的类方法。当然如果你不用使用 bind
这种冗长方式,也可以使用简洁方便的胖箭头表示方法。
更多JavaScript知识请关注PHP中文网JavaScript视频教程栏目
以上がJS で 'this' ポインタを処理するいくつかの方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。