JavaScriptの中のthisについて話します.

3528 ワード

JavaScriptの中のthisはいつも比較的に人に頭が痛くて、面接試験の特に聞きやすい問題です.以下はこの「知らないJavaScript」を参照して、thisという不思議なものを勉強します.
thisは何処を指していますか?
thisは、実行中にバインディングされており、作成時にバインディングされていません.コンテキストは、関数呼び出し時の様々な条件に依存します.thisの結合と関数宣言の位置は関係なく、関数の呼び出しに依存します.
したがって、thisは単に関数やオブジェクト自体を指すのではない.
thisの4つの結合方式
標準バインディング
デフォルトのバインディングとは、thisのデフォルトのバインディングです.
function foo() {
    console.log(this.a)
}

var a = 3;

foo(); // 3
注意:厳密なモードでは、このデフォルトのバインディング形式は成立しません.
var a = 3;

function foo() {
    "use strict";
    console.log(this.a)
}

foo(); // TypeError
陰式バインディング
暗黙的バインディングとは、obj.foo();のように、this所在関数がコンテキストで結合されていることを意味する.
function foo() {
    console.log(this.a);
}

var a = 1;
var obj = {
    a: 2,
    foo: foo
};

obj.foo(); // 2
オブジェクトの関数は参照関係だけで、オブジェクトと関数は2つの場所に存在します.したがって、他の場所では関数を使用して、陰的に結合されたオブジェクトとは関係がありません.次の二つの例を参照してください.
  • において、var myFoo = obj.fooのmyFoo変数はfoo()関数を参照し、objとは関係がない.したがって、myFooの実行関数挙動はデフォルトバインディングとなり、印刷結果は1となります.
  • function foo() {
        console.log(this.a);
    }
    
    var a = 1;
    var obj = {
        a: 2,
        foo: foo
    };
    
    var myFoo = obj.foo
    myFoo(); //     ,   1
    
  • は、コールバック関数においても、実はthisバインディングが失われている場合があります.コールバック関数obj.fooは、foo関数を参照しています.objオブジェクトとは関係ありません.
  • function foo() {
        console.log(this.a);
    }
    
    var a = 1;
    var obj = {
        a: 2,
        foo: foo
    };
    
    setTimeout(obj.foo, 300); // 1
    
    バインディングを表示
    明示的なバインディングとは、call、apply、bindを使用して、あるコンテキストを指定してバインディングすることであり、それらの一つの役割は、関数のためだけにコンテキストオブジェクトをハードバインドすることである.
    以前のコールバック関数はビッドを使って修正した後、私達のobjオブジェクトのa属性を印刷しました.
    function foo() {
        console.log(this.a);
    }
    
    var a = 1;
    var obj = {
        a: 2,
        foo: foo
    };
    
    setTimeout(obj.foo.bind(obj), 300);
    
    callとappyも同様で、関数にコンテキストを指定することによってハードバインディングを行い、ハードバインディングは一回のみとなります.call()方法の役割は、apply()方法と同様であり、call()方法が許容するのはパラメータリストであり、apply()方法が許容するのはパラメータ配列であるという違いがある.
    newバインディング
    newキーワードを使ってオブジェクトを作成するプロセスは、コンテキストを結合するプロセスでもありますので、newを使って作成したオブジェクトのthisも特に注意してください.
    newを使って関数を呼び出すか、またはコンストラクターの呼び出しが発生した場合、自動的に次の操作が実行されます.
  • 新しいオブジェクトを作成(または構造)します.
  • この新しいオブジェクトは[プロトタイプ]に接続されます.
  • この新しいオブジェクトは、関数呼び出しのthisに結合されます.
  • 関数が他のオブジェクトに戻っていない場合、new式の関数呼び出しは自動的にこの新しいオブジェクトに戻ります.
  • function foo(a) {
      this.a = a;
    }
    var bar = new foo(2);
    console.log( bar.a ); // 2
    
    new挙動の第三段階はthisバインディングを行うことであり,コードからnew挙動の確実な結合thisの能力を見ることもできる.
    thisの4つのバインディング方式の並べ替え
    4つの結合がすべてthisの方向を変えることができるなら、この4つの結合の優先度はどうなりますか?結論は:
    new    >      >      >     
    
    いくつかのシーンを一つのthisに結びつけることはめったにないですが、念のためにも.
    矢印関数
    thisについて最後に言いたいのはES 6の矢印関数です.
    function foo() {
        setTimeout(() => {
            //     this         foo()
            console.log(this.a);
        }, 100);
    }
    var obj = {
        a: 2
    };
    foo.call(obj); // 2
    
    完全に同じです.
    function foo() {
        var self = this; // lexical capture of this
        setTimeout(function () {
            console.log(self.a);
        }, 100);
    }
    var obj = {
        a: 2
    };
    foo.call(obj); // 2
    
    矢印関数についてはvar self = this;を覚えておけば十分です.
    これは実際には、現在のthisコンテキストをスコープで保存して、コールバック関数に伝達します.本質的にはthisの元からある機構を捨てたのです.
    最後に
    私たちは四つのよくあるthis結合方式と矢印関数の二つの角度システムからthis結合の知識点を学びました.これからはthis関連の知識点が怖くないと信じています.
    この文章にはまだ改善できるところがたくさんあります.もし何か意見や問題があれば、コメントで指摘してください.ありがとうございます
    おすすめ資料
  • あなたが知らないJavaScript(上巻)
  • Know this、use this!(thisの一般的な使い方をまとめます)