コールバック内で正しい「this」にアクセスする方法は?


1425

イベントハンドラーを登録するコンストラクター関数があります。

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', function () {
        alert(this.data);
    });
}

// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};

// called as
var obj = new MyConstructor('foo', transport);

ただし、dataコールバック内で作成されたオブジェクトのプロパティにアクセスできません。this作成されたオブジェクトではなく、別のオブジェクトを参照しているように見えます。

また、無名関数の代わりにオブジェクトメソッドを使用しようとしました。

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', this.alert);
}

MyConstructor.prototype.alert = function() {
    alert(this.name);
};

ただし、同じ問題が発生します。

正しいオブジェクトにアクセスするにはどうすればよいですか?


95
時々、私はある種の質問にうんざりしているので、標準的な答えを書くことにしました。これらの質問は100万回ほど回答されていますが、無関係な情報によって「汚染」されていない適切な質問と回答のペアを常に見つけることができるとは限りません。これはそれらの瞬間の1つであり、それらの質問の1つです(そして私は退屈しています)。このタイプの質問に実際に有効な正規の質問/回答があると思われる場合は、お知らせください。削除します。改善のための提案は大歓迎です!
Felix Kling、2013年



3
これに関する有用なTypeScriptページ。主にJSにも適用できます。
OndraŽižka2017

回答:


1791

知っておくべきこと this

this(別名「コンテキスト」)は、各関数内の特別なキーワードであり、その値は、関数が呼び出された方法にのみ依存し、定義された方法/時期/場所には依存しません。他の変数のような字句スコープの影響を受けません(矢印関数を除く、以下を参照)。ここではいくつかの例を示します。

function foo() {
    console.log(this);
}

// normal function call
foo(); // `this` will refer to `window`

// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`

// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`

詳細についてthisは、MDNのドキュメントをご覧ください。


正しい参照方法 this

使わない this

実際にはthis特にアクセスしたくないが、それが参照するオブジェクト。そのため、簡単な解決策は、そのオブジェクトも参照する新しい変数を作成することです。変数には任意の名前を付けることができますが、一般的なものはselfおよびthatです。

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function() {
        alert(self.data);
    });
}

selfは通常の変数なので、字句スコープのルールに従い、コールバック内からアクセスできます。これにthisは、コールバック自体の値にアクセスできるという利点もあります。

thisコールバックの明示的なセット-パート1

this値は自動的に設定されるため、の値を制御できないように見えますが、実際にはそうではありません。

すべての関数にはメソッド.bind [docs]がありthis、値にバインドされた新しい関数を返します。この関数の動作は、呼び出したものとまったく同じです.bindが、ユーザーthisが設定したものだけです。その関数がいつどのように呼び出されても、this常に渡された値を参照します。

function MyConstructor(data, transport) {
    this.data = data;
    var boundFunction = (function() { // parenthesis are not necessary
        alert(this.data);             // but might improve readability
    }).bind(this); // <- here we are calling `.bind()` 
    transport.on('data', boundFunction);
}

この場合、我々は、コールバックの結合されているthisの値にMyConstructorさんthis

注: jQueryのコンテキストをバインドする場合は、代わりにjQuery.proxy [docs]を使用してください。これを行う理由は、イベントコールバックのバインドを解除するときに関数への参照を保存する必要がないようにするためです。jQueryはそれを内部的に処理します。

ECMAScript 6:矢印関数を使用する

ECMAScript 6では、ラムダ関数と考えることができる矢印関数が導入されています。彼らには独自のthis拘束力はありません。代わりに、this通常の変数と同じようにスコープで検索されます。つまり、を呼び出す必要はありません.bind。それだけではありません。詳細については、MDNのドキュメントを参照してください。

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', () => alert(this.data));
}

thisコールバックのセット-パート2

コールバックを受け入れる一部の関数/メソッドは、コールバックのthis参照先の値も受け入れます。これは基本的に自分でバインドするのと同じですが、関数/メソッドがそれを行います。Array#map [docs]はそのような方法です。その署名は次のとおりです。

array.map(callback[, thisArg])

最初の引数はコールバックで、2番目の引数はthis参照する値です。これは不自然な例です:

var arr = [1, 2, 3];
var obj = {multiplier: 42};

var new_arr = arr.map(function(v) {
    return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument

注:this通常、値を渡すことができるかどうかは、その関数/メソッドのドキュメントに記載されています。たとえば、jQueryの$.ajaxメソッド[docs]には、次のオプションが記述されていますcontext

このオブジェクトは、すべてのAjax関連のコールバックのコンテキストになります。


一般的な問題:オブジェクトメソッドをコールバック/イベントハンドラーとして使用する

この問題のもう1つの一般的な症状は、オブジェクトメソッドがコールバック/イベントハンドラーとして使用される場合です。関数はJavaScriptの第一級の市民であり、「メソッド」という用語は、オブジェクトプロパティの値である関数の単なる俗語です。しかし、その関数には、その「包含」オブジェクトへの特定のリンクがありません。

次の例を考えてみます。

function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = function() {
    console.log(this.data);
};

関数this.methodはクリックイベントハンドラーとして割り当てられますが、がクリックされた場合、document.bodyログに記録される値はになりますundefined。これは、イベントハンドラー内ではのインスタンスではなくをthis参照するためdocument.bodyですFoo
最初にすでに述べたように、何をthis参照するかは、関数の定義方法ではなく、関数の呼び出し方法によって異なります。 コードが次のようである場合、関数がオブジェクトへの暗黙的な参照を持たないことがより明白になる可能性があります。

function method() {
    console.log(this.data);
}


function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = method;

解決策は上記と同じです:可能であれば、特定の値.bindに明示的にバインドするthisために使用します

document.body.onclick = this.method.bind(this);

または、匿名関数をコールバック/イベントハンドラーとして使用して、オブジェクトの「メソッド」として関数を明示的に呼び出し、オブジェクト(this)を別の変数に割り当てます。

var self = this;
document.body.onclick = function() {
    self.method();
};

または、矢印関数を使用します。

document.body.onclick = () => this.method();

39
フェリックス、私は以前にこの答えを読んだことがありますが、返事はありません。人々がを使用selfthatたり参照したりすることに不安を感じていthisます。thisは異なるコンテキストで使用されるオーバーロードされた変数なので、このように感じます。一方、self通常はローカルインスタンスに対応し、that通常は別のオブジェクトを参照します。他の多くの場所で表示されているので、あなたがこのルールを設定しなかったのを知っていますが、それが私がを使い始めた理由でもありますが_this、不均一な練習を除いて、他の人がどのように感じるかわかりませんその結果です。
vol7ron、2014

3
@FelixKlingは、このプロトタイプ関数の内部を使用すると、(通常)呼び出された方法に関係なく、常に期待どおりの動作が得られると想定しても安全でしょうか?プロトタイプ関数内でコールバックを使用する場合、bind()、self、またはそれの代替手段はありますか?
andig

5
@FelixKlingとに依存するFunction.prototype.call ()と便利な場合がありFunction.prototype.apply ()ます。特にapply ()私は多くの走行距離を得ました。bind ()他のオプションよりもバインドを使用する方がオーバーヘッドがわずかにある可能性があることはわかっていますが(確かではありませんが)、おそらく習慣から外して使用する傾向はあまりありません。
Nolo、2016年

5
すばらしい答えですが、クラス、new、またはこれをまったく使用しないというオプションのソリューションを追加することを検討してください。
Aluan Haddad

4
re arrow functions「代わりに、これは通常の変数と同じようにスコープ内で検索されます。」完全にこのクリックをしてくれました、ありがとう!() => this.clicked();)
alphanumeric0101

211

子コンテキスト内の親コンテキストにアクセスする方法はいくつかあります-

  1. bind()関数を使用できます。
  2. context / thisへの参照を別の変数内に格納します(以下の例を参照)。
  3. ES6の矢印関数を使用します。
  4. コード/関数の設計/アーキテクチャを変更する-このためには、JavaScriptの設計パターンを制御する必要があります 。

1. bind()関数を使用

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', ( function () {
        alert(this.data);
    }).bind(this) );
}
// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};
// called as
var obj = new MyConstructor('foo', transport);

使用している場合underscore.js- http://underscorejs.org/#bind

transport.on('data', _.bind(function () {
    alert(this.data);
}, this));

2 context / thisへの参照を別の変数に格納します

function MyConstructor(data, transport) {
  var self = this;
  this.data = data;
  transport.on('data', function() {
    alert(self.data);
  });
}

3アロー機能

function MyConstructor(data, transport) {
  this.data = data;
  transport.on('data', () => {
    alert(this.data);
  });
}

1
bind()オプションは、このオブジェクトのポインタを他のオブジェクトのthisに渡すだけですばらしいです(:ありがとう!
Stav Bodik

bind()はチャームのように機能します。本当にありがとうございます+1 :)
Anjana Silva

56

それはすべて、メソッドを呼び出す「魔法の」構文にあります。

object.property();

オブジェクトからプロパティを取得して一度に呼び出すと、オブジェクトはメソッドのコンテキストになります。同じメソッドを個別のステップで呼び出す場合、コンテキストはグローバルスコープ(ウィンドウ)です。

var f = object.property;
f();

メソッドの参照を取得すると、それはオブジェクトにアタッチされなくなり、単なる関数への参照になります。コールバックとして使用する参照を取得した場合も同様です。

this.saveNextLevelData(this.setAll);

ここで、コンテキストを関数にバインドします。

this.saveNextLevelData(this.setAll.bind(this));

jQueryを使用し$.proxybindいる場合は、すべてのブラウザーでサポートされているわけではないため、代わりにメソッドを使用する必要があります。

this.saveNextLevelData($.proxy(this.setAll, this));

33

「コンテキスト」の問題

「コンテキスト」という用語は、thisによって参照されるオブジェクトを指すために使用されることがあります。ECMAScriptのthisと意味的または技術的に適合しないため、その使用は不適切です。

「コンテキスト」とは、意味を追加する何かを取り巻く状況、または追加の意味を与える前後の情報を意味します。用語「コンテキスト」を参照するためにECMAScriptのに使用されている実行コンテキストすべてのパラメータ、範囲であり、この一部の実行コードの範囲内です。

これはECMA-262セクション10.4.2に示されています。

ThisBindingを、呼び出し実行コンテキストのThisBindingと同じ値に設定します。

これは、これが実行コンテキストの一部であることを明確に示しています。

実行コンテキストは、実行されるコードに意味を追加する周囲の情報を提供します。thisBindingだけではなく、はるかに多くの情報が含まれています。

したがって、この値は「コンテキスト」ではなく、実行コンテキストの一部にすぎません。これは基本的に、任意のオブジェクトへの呼び出しによって、厳密モードで、任意の値に設定できるローカル変数です。


この答えには同意できません。「実行コンテキスト」という用語の存在は、それが「実行」の他の使用を禁止する以上に、「コンテキスト」の他の使用を禁止しない。表現するのにもっと良い用語があるかもしれthisませんが、ここでは何も提供されていません。おそらく「コンテキスト」の扉を閉めるには遅すぎるでしょう。
Roamer-1888

@ Roamer-1888-編集ありがとうございます。あなたの言う通りですが、私の主張は、「実行コンテキスト」の存在に依存せず、他の目的で「コンテキスト」を排除します。むしろ、それは技術的およびセマンティックの両方の観点から不適切な「コンテキスト」に基づいています。また、「これ」ではなく「コンテキスト」を使用することは廃止されつつあると思います。thisまたはthisBindingの代替用語を見つける理由はわかりません。これは単に難読化し、ある時点で「コンテキスト」が実際にはthisであり、いずれにしても「コンテキスト」ではないことを説明する必要があることを意味します。:-)
RobG

「実行」が単なる形容詞である実行コンテキストの一部であることをすでに認めている場合、これは決して「コンテキスト」ではないとは言えません。
Roamer-1888

@ Roamer-1888 —この時点以降、この会話を続けるつもりはありません。はい、これは実行コンテキストの一部です。それコンテキストだと言うことは、チームの1人のプレーヤーがチームであると言うようなものです。
RobG

RobG、続けたくないのは残念です。それは興味深い議論です。お時間をいただきありがとうございます。
Roamer-1888

31

「これ」のキーワードについて知っておくべきです。

私の見解によれば、「これ」を3つの方法で実装できます (自己/矢印機能/バインド方法)

関数のthisキーワードの動作は、JavaScriptでは他の言語とは少し異なります。

厳格モードと非厳格モードの間にもいくつかの違いがあります。

ほとんどの場合、この値は関数の呼び出し方法によって決まります。

実行時の代入では設定できず、関数を呼び出すたびに異なる場合があります。

ES5はbind()メソッドを導入し、関数のthisの値を、それがどのように呼び出されたかに関係なく設定します。

ES2015では、独自のthisバインディングを提供しないarrow関数が導入されました(それは、囲んでいる字句コンテキストのthis値を保持しています)。

方法1: Self-Selfは、コンテキストが変化しても、元のthisへの参照を維持するために使用されています。これは、イベントハンドラー(特にクロージャー)でよく使用される手法です。

リファレンスhttps : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function () {
        alert(self.data);
    });
}

方法2:アロー関数-アロー関数式は、正規の関数式の構文的にコンパクトな代替です。

ただし、this、arguments、super、またはnew.targetキーワードへの独自のバインディングはありません。

アロー関数式はメソッドとしては不適切であり、コンストラクターとして使用することはできません。

リファレンスhttps : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

  function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data',()=> {
        alert(this.data);
    });
}

Method3:Bind- bind()メソッドは新しい関数を作成し、

呼び出されると、thisキーワードが指定された値に設定されます。

新しい関数が呼び出されたときに提供される引数の前に、指定された一連の引数を使用します。

リファレンス: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind

  function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data',(function() {
        alert(this.data);
    }).bind(this);

25

まず、のコンテキストでのキーワードの明確な理解scopeと動作が必要thisですscope

thisscope


there are two types of scope in javascript. They are :

   1) Global Scope

   2) Function Scope

つまり、グローバルスコープはウィンドウオブジェクトを指します。グローバルスコープで宣言された変数はどこからでもアクセスできます。一方、関数スコープは関数内にあります。関数内で宣言された変数は通常、外部からアクセスできません。thisグローバルスコープのキーワードは、ウィンドウオブジェクトを参照します。this内部関数はウィンドウオブジェクトも参照します。したがって、自分で選択したコンテキストを示すthisための操作方法を見つけるまで、常にウィンドウを参照しますthis

--------------------------------------------------------------------------------
-                                                                              -
-   Global Scope                                                               -
-   ( globally "this" refers to window object)                                 -     
-                                                                              -
-         function outer_function(callback){                                   -
-                                                                              -
-               // outer function scope                                        -
-               // inside outer function"this" keyword refers to window object -                                                                              -
-              callback() // "this" inside callback also refers window object  -

-         }                                                                    -
-                                                                              -
-         function callback_function(){                                        -
-                                                                              -
-                //  function to be passed as callback                         -
-                                                                              -
-                // here "THIS" refers to window object also                   -
-                                                                              -
-         }                                                                    -
-                                                                              -
-         outer_function(callback_function)                                    -
-         // invoke with callback                                              -
--------------------------------------------------------------------------------

thisコールバック関数の内部を操作するさまざまな方法:

ここにPersonというコンストラクタ関数があります。これは、というプロパティがあるnameと呼ばれる4つの方法をsayNameVersion1sayNameVersion2sayNameVersion3sayNameVersion4。4つすべてに1つの特定のタスクがあります。コールバックを受け入れてそれを呼び出します。コールバックには、Personコンストラクター関数のインスタンスのnameプロパティをログに記録する特定のタスクがあります。

function Person(name){

    this.name = name

    this.sayNameVersion1 = function(callback){
        callback.bind(this)()
    }
    this.sayNameVersion2 = function(callback){
        callback()
    }

    this.sayNameVersion3 = function(callback){
        callback.call(this)
    }

    this.sayNameVersion4 = function(callback){
        callback.apply(this)
    }

}

function niceCallback(){

    // function to be used as callback

    var parentObject = this

    console.log(parentObject)

}

次に、Personコンストラクターからインスタンスを作成し、sayNameVersionX(Xは1,2,3,4を指す)メソッドのさまざまなバージョンを呼び出して、インスタンスを参照するために内部のコールバックをniceCallback操作する方法をいくつか見てみましょう。thisperson

var p1 = new Person('zami') // create an instance of Person constructor

練る :

bindが行うことは、thisキーワードを指定された値に設定して新しい関数を作成することです。

sayNameVersion1そして、sayNameVersion2使用バインド操作するために、thisコールバック関数の。

this.sayNameVersion1 = function(callback){
    callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
    callback()
}

最初thisのメソッドは、メソッド自体の内部でコールバックを使用してバインドします。2番目のコールバックは、オブジェクトにバインドして渡されます。

p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method

p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback

電話する:

方法は、以下のように使用されると呼び出された関数内の、それに取り付けられています。first argumentcallthiscall

sayNameVersion3callを操作しthisて、ウィンドウオブジェクトではなく、作成した人物オブジェクトを参照するために使用 します。

this.sayNameVersion3 = function(callback){
    callback.call(this)
}

そしてそれは次のように呼ばれます:

p1.sayNameVersion3(niceCallback)

適用:

と同様にcall、の最初の引数applyは、thisキーワードによって示されるオブジェクトを参照します。

sayNameVersion4personオブジェクトを参照するapplyための操作thisに使用します

this.sayNameVersion4 = function(callback){
    callback.apply(this)
}

そして、それは次のように呼び出されます。単にコールバックが渡され、

p1.sayNameVersion4(niceCallback)

1
答えに関する建設的な批判は高く評価されます!
AL-zami 2017

1
グローバルスコープのthisキーワードは、必ずしもウィンドウオブジェクトを参照する必要はありません。これはブラウザでのみ当てはまります。
ランドールフラッグ2018年

1
@RandallFlagg私はブラウザの観点からこの回答を書きました。必要に応じてこの回答を自由に強化してください:)
AL-zami

19

これをsetTimeout()にバインドすることはできません。これは常にグローバルオブジェクト(ウィンドウ)で実行されるためthis、コールバック関数のコンテキストにアクセスする場合は、コールバック関数を使用bind()して次のように実現できます。

setTimeout(function(){
    this.methodName();
}.bind(this), 2000);

9
これは、既存の回答とどのように違うのですか?
Felix Kling 2017年

13

質問thisは、JavaScriptでのキーワードの動作を中心に展開します。this以下のように異なる動作をします、

  1. の値thisは通常、関数実行コンテキストによって決定されます。
  2. グローバルスコープでthisは、グローバルオブジェクト(windowオブジェクト)を参照します。
  3. いずれかの機能で厳密モードが有効になっている場合、の値は厳密モードthisundefined同様になりundefinedwindowオブジェクトの代わりにグローバルオブジェクトが参照されます。
  4. ドットの前に立っているオブジェクトは、thisキーワードがバインドされる対象です。
  5. 私たちは、と明示的にこの値を設定することができcall()bind()およびapply()
  6. ときnewキーワードは(コンストラクタ)が使用され、これは、新しいオブジェクトが作成されることにバインドされています。
  7. アロー関数はバインドしないthis —代わりに、this字句的にバインドされます(つまり、元のコンテキストに基づいて)

ほとんどの回答が示唆しているように、アロー関数、bind()メソッド、または自己変数を使用できます。Google JavaScript Style Guideからラムダ(矢印関数)に関するポイントを引用します

f.bind(this)よりも、特にgoog.bind(f、this)よりも矢印関数を使用することをお勧めします。const self = thisと書くことは避けてください。矢印関数は、予期しない追加の引数を渡すコールバックに特に役立ちます。

Googleでは、バインドやラムダではなくラムダを使用することを明確に推奨しています const self = this

したがって、最良の解決策は、以下のようにラムダを使用することです。

function MyConstructor(data, transport) {
  this.data = data;
  transport.on('data', () => {
    alert(this.data);
  });
}

参照:

  1. https://medium.com/tech-tajawal/javascript-this-4-rules-7354abdb274c
  2. arrow-functions-vs-bind

この質問は、コールバックとして関数/メソッドを使用することについて特にです。あなたの答えは、stackoverflow.com / q / 3127429/218196に適しているかもしれません。
Felix Kling

@FelixKlingはい質問は、関数/メソッドをコールバックとして使用することに関するものです。その主な問題は、thisキーワードの処理によるものthisでした。コールバックとして関数/メソッドを使用することについて、1つ目と2つ目で答えを2つに分けた理由です。回答を自由に編集してください。
Code_Mode

4つ目のポイントは曖昧に表現されています。「thisオブジェクトをメソッドとしてコールバックとして使用するときの問題」例を考えてみます。この場合、適切なオブジェクトはドットの前に立っていますが、コンテキストはそのオブジェクトではありません。
bleistift2

7

現在、クラスがコードで使用されている場合、別のアプローチが可能です。

クラスフィールドのサポートにより 、次の方法で作成できます。

class someView {
    onSomeInputKeyUp = (event) => {
        console.log(this); // this refers to correct value
    // ....
    someInitMethod() {
        //...
        someInput.addEventListener('input', this.onSomeInputKeyUp)

確かに内部では、コンテキストをバインドするのは古い古き良き矢印関数ですが、この形式では、明示的なバインドの方がはるかに明確に見えます。

ステージ3プロポーザルなので、今のところ(08/2018)のように処理するには、babelと適切なbabelプラグインが必要です。


2
これは、Typescriptでpublic methodName = (params) => { body }クラスを動作させる方法とまったく同じです。
yeyeyerman

5

DOM2thisイベントリスナー内でバインドするための標準的な方法であり常にリスナーを削除できる別のアプローチは(他の利点の中でも特に)、インターフェースhandleEvent(evt)からのEventListenerメソッドです。

var obj = {
  handleEvent(e) {
    // always true
    console.log(this === obj);
  }
};

document.body.addEventListener('click', obj);

使用の詳細については、handleEventこちらをご覧くださいhttps : //medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38


0

this JS:

thisJS のの値は、関数の定義方法ではなく、関数の呼び出し方法によって100%決定されます。「ドットルールの左」thisによっての値を比較的簡単に見つけることができます。

  1. functionキーワードを使用して関数が作成されると、値thisは呼び出される関数のドットの左側のオブジェクトです
  2. ドットの左側にオブジェクトがない場合this、関数内の値は多くの場合、グローバルオブジェクト(globalノード内window、ブラウザー内)です。thisここではキーワードを使用することはお勧めしませんwindow
  3. アロー関数やFunction.prototype.bind()、の値を修正できる関数を使用して作成された関数などの特定の構成体が存在しますthis。これらはルールの例外ですが、の値を修正するのに非常に役立ちますthis

nodeJSの例

module.exports.data = 'module data';
// This outside a function in node refers to module.exports object
console.log(this);

const obj1 = {
    data: "obj1 data",
    met1: function () {
        console.log(this.data);
    },
    met2: () => {
        console.log(this.data);
    },
};

const obj2 = {
    data: "obj2 data",
    test1: function () {
        console.log(this.data);
    },
    test2: function () {
        console.log(this.data);
    }.bind(obj1),
    test3: obj1.met1,
    test4: obj1.met2,
};

obj2.test1();
obj2.test2();
obj2.test3();
obj2.test4();
obj1.met1.call(obj2);

出力:

ここに画像の説明を入力してください

出力を1つずつ説明します(2番目から始まる最初のログは無視します)。

  1. thisですobj2ので、ドットルールの左側の、私たちはどのように見ることができますtest1と呼ばれていますobj2.test1();obj2ドットの左側、つまりthis値です。
  2. obj2ドットの左側ですが、メソッドtest2obj1介してバインドされていbind()ます。したがって、this値はobj1です。
  3. obj2呼び出される関数のドットの左側ですobj2.test3()。したがってobj2の値になりthisます。
  4. この場合:obj2.test4() obj2はドットの左側です。ただし、矢印関数には独自のthisバインディングがありません。したがって、最初にログに記録されたオブジェクトであるthis外部スコープの値にバインドmodule.exportsされます。
  5. 関数thisを使用しての値を指定することもできますcall。ここでは、目的のthis値を引数として渡すことができます(obj2この場合)。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.