JavaScriptの中のthisは問題を指します.

4401 ワード

まず、thisの指向は関数定義の時には確定できません.関数実行時にのみ、thisが誰を指しているのかを判断できます.コンテキスト環境によって変化します.グローバル環境、イベント処理関数、関数内部、矢印関数内部、オブジェクト方法内部、構造関数、プロトタイプチェーン上の関数から、this指向問題を説明します.
1.グローバル環境は、windowの方法で呼び出す時、thisはずっとwindowを指します.set Timeoutはwindowの方法ですので、ここでthisはwindowを指します.
div
var box = document.getElementById("box"); box.onclick = function(){ setTimeout( function(){ console.log( this ); //window this.style.backgroundColor = "red"; //Cannot set property 'backgroundColor' of undefined },1000 ) }
よく使われるwindowの方法は、set Interval()、setTimeout()、alert()などです. 
2.イベント処理中のthisは、行間が自己実行の匿名関数でない限り、イベントをトリガするタグを指す.
div
div1
div2
box.onclick = function(){ console.log(this); // this, ,this }
3.関数内部
(1)関数の直接実行
非厳格モードでは、thisはデフォルトでwindowを指します.
function fn(){
    console.log(this);
}
fn();    //window
window.fn();    //window
厳密なモードでは、windowを書かないときはundefinedを指します. 
function fn(){
    "use strict"
    console.log(this);
}
fn();    //undefined
window.fn();    //window
(2)call、appyとbindの中のthis
call、applyとbindメソッドは、関数運転時のthisの指向を変えることができます.
関数.call()はこの関数を直接呼び出します.callの0番目のパラメータは関数実行時のthisです.後ろのパラメータは関数実行時のパラメータです.
function fn(m,n){
    console.log( this.a,m,n );    //this  {a: 1}    
}	
fn.call( {a: 1},2,3 );    //1 2 3
関数.apply()は、2つのパラメータのうち、最初のパラメータは関数実行時のthisであり、2番目のパラメータはパラメータ配列である.
var obj = {name:'obj'};

obj.fn =function(a, b){
    a = b;
    console.log(this)    //{name: "o"}
};

var o = {name:'o'};
obj.fn.apply(o, [1,3])

関数.bind()は新しい関数を返します.これ以外はcallと同じように、thisはbindの最初のパラメータを指します.後ろのパラメータは関数実行時のパラメータです.しかし、もう一つの関数は、再びbindはそのthis方向を修正しません.
var obj =  {
    name:'zs',
    fun:function(){
        setInterval(function(){
            console.log(this.name);
        }.bind(this),1000);//    bind          this   obj
    }
};
obj.fun();
なお、最初のパラメータが直接的に数字の種類である場合、thisはNumberを指します.
function fn(){
    console.log(this.a);
}
var fn1 = fn.bind( {a: 2} );
var fn2 = fn.bind( {a: 3} );
fn1();    //2
fn2();    //3

var fn3 = fn1.bind( {a:100} );
fn3();    //2

function foo(){
    console.log(this);
}
var foo1 = foo.bind(1);
foo1();    //Number
(3)矢印関数の内部
矢印関数内部のthisは、定義された環境の中でthisと一致しています.bind、call、applyは矢印関数の内部指向を変更することができません.
box
var fn = ()=>{ console.log( this ); } fn(); //window box.onclick = function(){ setTimeout( ()=>{ this.style.backgroundColor = "red"; console.log( this ); //<div id="box">box</div> },500 ); } //bind,call,apply var fn1 = fn.bind( "abc" ); fn1(); //window
 4.オブジェクト内部
オブジェクト内で定義されている矢印関数は、呼び出し時にthisがwindowを指します.定義時の環境はwindowです.
オブジェクト内で定義されている一般関数は、呼び出し時に、thisがオブジェクトを指します.
var a = 1;
var obj = {
    a: 2,
    fn1: ()=>{
        console.log( this.a )
    },
    fn2: function(){
        console.log( this.a )
    }
}
obj.fn1();	//1 this  window
obj.fn2();	//2 this     
オブジェクト関数の内部で定義されている関数は、戻り値が関数の場合、通常の関数でも矢印の関数でも、この戻り関数のthisはwindowを指します. 
var a = 1;
var obj = {
    a: 2,
    fn1: function(){
        console.log( this.a )
        return function(){
            console.log( this.a )
        }
    },
    fn2: ()=>{
        console.log( this.a )
        return ()=>{
            console.log( this.a )
        }
    }
}

var innerFn1 = obj.fn1();   //2
innerFn1();                 //1

var innerFn2 = obj.fn2();   //1
innerFn2();                 //1
 オブジェクト内のメソッドを呼び出した場合は、呼び出しのコンテキスト環境に応じて判定します.直接呼び出しであれば、この方法を直接呼び出すオブジェクトを指す.この方法を別の新しい定義の変数に割り当てたら、windowを指します.
var a = 1;
var obj = {
    a: 2,
    o: {
        a: 3,
        fn: function(){
            console.log(this.a)
        }
    }
};
obj.o.fn();    //3 this  obj    o
var temp = obj.o.fn;
temp();        //1 this  window