javascriptのthisは問題を指します.

32467 ワード

前言
thisの指す問題については、以前からこのような言い方を信じていました.誰かが呼んだら、thisは誰を指しますか?しかし、開発にはいくつかの異なる状況があります.だからここでthisに対する認識と理解について説明します.
まず、私たちが知っているのは、thisの指向は、関数が呼び出された時に確定されます.つまりコンテキストが作成されたときに決定されます.
例1:
function fn() {
	var a = 10;
	console.log(this); // window
	console.log(this.a); // undefined
}
fn();
上で述べたように、thisは最終的にそのオブジェクトを呼び出すことを指しています.ここの関数fnは実際にWindowオブジェクトによって作られています.以下のコードで証明されます.
function fn() {
	var a = 10;
	console.log(this); // window
	console.log(this.a); // undefined
}
window.fn();
実はalertもwindowの属性の一つで、windowがつけたのです.
例2:
var obj = {
	a = 10;
	fn:function() {
		console.log(this); // {a: 10, fn: ƒ}
		console.log(this.a); // 10
	}
}
obj.fn();
ここでのthisの対象はobjです.このfnを呼び出してobj.fn()を通じて実行しますので、自然に対象objを指します.また、thisの指向は関数が作成される時には決められません.呼び出しの時にのみ決定されます.呼び出しの人は誰を指しますか?
実は上の二つの例も正確ではないです.次の例を見てみます.例3:
var obj = {
	a = 10;
	fn: function() {
		console.log(this.a); // 10
		console.log(this); // {a: 10, fn: ƒ}
	}
}
window.obj.fn();
例3と例2はほぼ同じですが、ここのthisはどうしてwindowを指すのではなく、上の理論によれば、最終的にthisが指すべきはその対象windowを呼び出すべきで、objではありません.はい、話は多くないです.とりあえず、なぜthisがwindowを指していないのかはともかく、コードを見てみます.
var obj = {
     a: 10,
     b: {
      		a: 20,
            fn: function () {
               console.log(this); // {a: 20, fn: ƒ}
               console.log(this.a); // 20

            }
        }
 }
 
obj.b.fn();
ここも同じ対象のobjポイントですが、thisは実行していません.前に言ったのは間違いですか?実は最初に言ったのは正確ではないとしか言えません.これから補充するのがポイントです.
ケース1:もし一つの関数にthisがあると、前のレベルのオブジェクトに呼び出されず、非厳格モードではthisがwindowを指します.ケース2:もし一つの関数にthisがあると、この関数は前のレベルのオブジェクトに呼び出されます.thisは前のレベルのオブジェクトを指します.ケース3:一つの関数の中にthisがあると、この関数は複数のオブジェクトを含んでいますが、この関数は一番外側のオブジェクトによって呼び出されたものです.thisが指しているのはその前のレベルのオブジェクトだけです.例3はこの点を証明することができます.次にいくつかの例を説明します.
var obj = {
    a: 10,
    b: {
        fn: function () {
            console.log(this); // {fn: ƒ}
            console.log(this.a); // undefined

        }
    }
}

obj.b.fn()
オブジェクトbに属性aがないにもかかわらず、このthisはオブジェクトbを指しています.thisは前のオブジェクトだけを指しています.このオブジェクトの中にthisが必要なものがあるかどうかに関わらず.また特殊な場合があります.
var obj = {
    a: 10,
    b: {
        a: 20,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); // window
        }
    }
}

var fun = obj.b.fn;
fun();
ここのthisはwindowを指していますが、ここに来たらちょっと蒙古さがありますか?つまり、「this」は永遠に最後に呼び出された対象を指します.つまり、実行時に誰が呼び出したかを見ます.例4では、関数fnはオブジェクトbによって参照されているが、変数funにfnを付与する際には実行されないので、最終的にはwindowを指す.
構造関数this
fnuction Fun() {
	this.str = "    "
}
var a = new Fun();
console.log(a.str);  //     
ここでオブジェクトaが関数Funの中のstrを注文できるのは、newキーワードがthisの指向を変えることができるからです.このthisをオブジェクトaに向けて、ここで変数aでFunのインスタンスを作成しました.Funをオブジェクトaにコピーしたのと同じです.このときは作成しただけで実行されていません.この関数Funを呼び出したのは対象aです.なぜ対象aにはstrがありますか?Fun関数をオブジェクトaにコピーしたので、newキーワードを使ってコピーしたのと同じです.
その他に、私達は自分でthisの指向を変えることができます.javascriptでcall、appy、bindで解決します.普通はthisの環境を指定します.例えば、私たちは通常このような問題に遭遇します.
var a = {
    name: "  ",
    fn:function(){
        console.log(this.name);
        // console.log(this);
    }
}
var b = a.fn;
console.log(b()); // undefined
私たちはオブジェクトaの中のnameをプリントしたいですが、undefinedはどのような状況ですか?a.fn()を直接実行すればいいです.
var a = {
    name: "  ",
    fn:function(){
        console.log(this.name);
    }
}
console.log(a.fn()); //   
ここで印刷できるのはここのthisが関数aを指しているからです.なぜ上のはaを指すのではないですか?目的を達成するためには、以下の方法で実現する必要があります.1、コール()
var a = {
    name:"  ",
    fn:function(){
        console.log(this.name); //   
    }
}
var b = a.fn;
b.call(a);
call方法によって、最初のパラメータにbをどの環境に追加しますか?簡単に言えば、thisはその対象を指します.call方法は、最初のパラメータ以外にも複数のパラメータを追加できます.
var a = {
    name:"  ",
    fn:function(m,n){
        console.log(this.name); //  
        console.log(m+n); // 3
    }
}
var b = a.fn;
b.call(a,1,2);
2、apply()apply方法とcall方法は似ています.thisの方向を変えることもできます.
var a = {
    name:"  ",
    fn:function(){
        console.log(this.name); //  
    }
}
var b = a.fn;
b.apply(a);
同様に、複数のパラメータもありますが、異なるのは、2番目のパラメータは1つの配列でなければなりません.
var a = {
    name:"  ",
    fn:function(m,n){
        console.log(this.name); //  
        console.log(m+n); //30
    }
}
var b = a.fn;
b.apply(a,[10,20]);
または
var a = {
    name:"  ",
    fn:function(m,n){
        console.log(this.name); //  
        console.log(m+n); //30
    }
}
var b = a.fn;
var arr = [10,20]
b.apply(a,arr);
注意:callとappyの最初のパラメータがnullであれば、thisはwindowオブジェクトを指します.
var a = {
    name: "  ",
    fn:function(){
        console.log(this); //Window
    }
}
var b = a.fn;
b.apply(null);
3、bind()方法とcall、apply方法は少し違っていますが、いずれにしてもthisを変えるための指向です.まず、その違いを説明しましょう.

var a = {
    name: "  ",
    fn:function(){
        console.log(this.name);
    }
}
var b = a.fn;
b.bind(a);
コードが印刷されていないことを発見しました.これはビッドとcall、applyの方法の違いです.実際にビッドが返したのは修正済みの関数です.
var a = {
	name:"  ",
	fn:function(){
		console.log(this.name);
	}
}
var b = a.fn;
var c = b.bind(a);
console.log(c); //ƒ (){console.log(this.name);}
じゃ、関数cを実行してみます.オブジェクトaの中のnameを印刷できますか?
var a = {
	name:"  ",
	fn:function(){
		console.log(this.name); //   
	}
}
var b = a.fn;
var c = b.bind(a);
c();
OKですまた、bindには複数のパラメータがあり、パラメータが実行される場合は再度追加することもできますが、パラメータは形参の順に行われます.
var a = {
	name:"  ",
	fn:function(num1,num2,num3){
		console.log(this.name); //  
		console.log(num1,num2,num3); // 10  1  2
	}
}
var b = a.fn;
var c = b.bind(a,10);
c(1,2);
まとめ:callとappyはコンテキストのthisを変えてすぐにこの関数を実行します.bind方法は対応する関数がいつ呼び出したいかを教えてくれます.そしてパラメータを実行する時に追加してもいいです.これは違いです.自分の実際の状況によって使用を選択します.