ホームページ  >  記事  >  ウェブフロントエンド  >  JS で 'this' ポインタを処理するいくつかの方法

JS で 'this' ポインタを処理するいくつかの方法

尚
転載
2020-06-18 17:18:031916ブラウズ

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. メソッド分離の問題

フィールド firstNamelastName# を含むクラス 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() メソッド内の thisagent と同等です。

補助関数が

agent.getFullName メソッドを実行するとどうなるか:

execute(agent.getFullName); // => 'undefined undefined'

実行結果が正しくありません:

'未定義 未定義'、これisthis 間違ったポインティングによって引き起こされる問題。

ここで、

getFullName() メソッドの this の値はグローバル オブジェクト (ブラウザ環境の window) です。 thiswindow, ${window.firstName} ${window.lastName} と等しくなります。実行結果は '未定義 未定義' です。 。

これは、

execute(agent.getFullName) が呼び出されたときにメソッドがオブジェクトから切り離されるために発生します。基本的に、行われるのは単なる通常の関数呼び出しです (メソッド呼び出しではありません):

execute(agent.getFullName); // => 'undefined undefined'

// 等价于:

const getFullNameSeparated = agent.getFullName;
execute(getFullNameSeparated); // => 'undefined undefined'

これは、メソッドがオブジェクトから切り離されるときに呼び出されるものです。メソッドが切り離されて実行されると、

this 元のオブジェクトとの接続はありません。

メソッド内の

this が正しいオブジェクトを指していることを確認するには、これを行う必要があります。

  1. メソッドをプロパティ アクセサーとして実行します。 :

    agent.getFullName()

  2. または、
  3. this を包含オブジェクトに静的にバインドします (アロー関数、.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(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

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(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

アロー関数は、

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); // => &#39;undefined undefined&#39;

残念ながら、新しいクラス構文を使用した場合でも、

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(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

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(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;

胖箭头方法getFullName =() =>{…}绑定到类实例,即使将方法与其对象分离。

这种方法是在类中绑定this的最有效和最简洁的方法。

6. 总结

与对象分离的方法会产生 this 指向不正确问题。静态地绑定this,可以手动使用一个附加变量self来保存正确的上下文对象。然而,更好的替代方法是使用箭头函数,其本质上是为了在词法上绑定this

在类中,可以使用bind()方法手动绑定构造函数中的类方法。当然如果你不用使用 bind 这种冗长方式,也可以使用简洁方便的胖箭头表示方法。

更多JavaScript知识请关注PHP中文网JavaScript视频教程栏目

以上がJS で 'this' ポインタを処理するいくつかの方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。