JavaScriptの中のthisは問題を指します.
4401 ワード
まず、thisの指向は関数定義の時には確定できません.関数実行時にのみ、thisが誰を指しているのかを判断できます.コンテキスト環境によって変化します.グローバル環境、イベント処理関数、関数内部、矢印関数内部、オブジェクト方法内部、構造関数、プロトタイプチェーン上の関数から、this指向問題を説明します.
1.グローバル環境は、windowの方法で呼び出す時、thisはずっとwindowを指します.set Timeoutはwindowの方法ですので、ここでthisはwindowを指します.
2.イベント処理中のthisは、行間が自己実行の匿名関数でない限り、イベントをトリガするタグを指す.
(1)関数の直接実行
非厳格モードでは、thisはデフォルトでwindowを指します.
call、applyとbindメソッドは、関数運転時のthisの指向を変えることができます.
関数.call()はこの関数を直接呼び出します.callの0番目のパラメータは関数実行時のthisです.後ろのパラメータは関数実行時のパラメータです.
矢印関数内部のthisは、定義された環境の中でthisと一致しています.bind、call、applyは矢印関数の内部指向を変更することができません.
オブジェクト内で定義されている矢印関数は、呼び出し時にthisがwindowを指します.定義時の環境はwindowです.
オブジェクト内で定義されている一般関数は、呼び出し時に、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の中のthiscall、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