一、全局下,this一般都指向window
全局下,ES5非严格模式,下面的this都是window。
console.log(this);
function abc(){console.log(this);
}
abc();
二、对象中的this
1、最常见的this情况:
var a=100;var obj={a:1,b:function(){console.log(this);//这个this是当前对象// 谁调用b方法,this就是谁},// this是当前对象外的this指向,这里应该是windowc:this.a
}
var obj1 = obj;
obj = {};
obj1.b();//浅复制而已,引用没变
2、如果在对象的属性对象中:
var a=1000;var obj = {a: 1,b: {c: this.a, //运行到此时obj还没生成,this还是指向window 创建时 还没生成d: function () {console.log(this); //函数被调用的时候才会执行这句话,同样,谁调用指向谁}}}
console.log(obj);
obj.b.d();
3、如果obj已经创建完,再给obj增加属性,那么此时的obj.b的this还是指向window。
var a=2000;var obj={a:1
}
console.log(obj); obj.b={c:this.a,d:function(){console.log(this);}
}console.log(obj);
4、如果是对象中的属性函数下又新建对象,this指向外层对象obj。
var obj = {a: 1,b: function () {// thisvar obj2 = {// this指当前对象外this的指向,这里的this指向是objc: this.a}console.log(obj2.c);}
}obj.b();
三、回调函数中的this
回调:函数在另一个函数的参数里,然后被调用,就叫回调。
1、一般的回调函数:(this被重定向到window)
function ab(fn) {fn();
}
function cd() {// this指向windowconsole.log(this);
}ab(cd);
2、对象中的回调:(this被重定向到window)
var obj = {a: function (fn) {fn();},b: function () {// 如果直接执行obj.b() 这里的this应该是obj对象// 如果通过上面a方法回调执行当前b的时候,this被重定向到windowconsole.log(this);}
}obj.a(obj.b);
3、事件是特殊的回调函数,事件回调函数中的this都是被侦听的对象:
document.addEventListener("click", clickHandler);function clickHandler(e) {console.log(this);// this===e.currentTarget
}
4、把函数写在方法中(匿名的回调函数),this都重定向到window:(不论这个方法放在哪)
var obj = {a: function () {setTimeout(function () {console.log(this)//window}, 100);// 所有的函数一旦被写在一个方法中,这个函数就是匿名的回调函数,在该函数中this指向windowsetInterval(function () {console.log(this);}, 100)var arr = [1, 2, 3];arr.map(function () {console.log(this);//window// forEach,filter,reduce,some,every,flatMap});new Promise(function (resolve, reject) {console.log(this);//window})}
}
obj.a();
new Promise(function (resolve, reject) {console.log(this);//window
})
四、事件函数中的this
事件函数是特殊的回调函数,使用时不会被重定向到window,而是侦听对象;因为太特殊了,单独拿出来再了解了解。
事件侦听的回调函数,this被重新处理,this指向被侦听的对象。
(1)最常用的看上面。
(2)放到其他地方也一样。比如放到对象里:
var obj={a:function(){document.addEventListener("click",this.b);this.b();},b:function(e){// 因为b函数是事件侦听的回调函数,因此这里this指向事件侦听的对象,也就是documentconsole.log(this);console.log(e);//侦听到的事件}
}
obj.a();
五、ES6类中的this
一般都是指向当前实例对象,但是静态属性、静态方法都可以指向当前类。
但是要注意:对于面向对象语言来说,一般在静态属性和方法中是不允许使用this这个概念的。
class Box{
// 在外面定义,ES7后才有的
// 这里的内容是constructor执行后才赋的值
//其实在这儿定义的,跟在constructor里定义差不多
b=333;
a=this.b;
static b=444;
static a=this.b;//一旦被设为静态属性,this指向都会被设置为当前的类名Box
constructor(){
// this指向当前实例对象console.log(this);console.log(this.a,Box.a);this.b=111;this.a=this.b;Box.b=222; //也是静态属性Box.a=Box.b;console.log(this.a,Box.a);
}
play(){// 这里的this都是实例化的对象console.log(this.a,Box.a);console.log(this);
}static run(){console.log(this);// 因为使用static定义的方法,this指向为当前类名// 对于面向对象语言来说,一般在静态属性和方法中不允许使用this这个概念
}}
var a=new Box();
a.play();class Ball extends Box{
constructor(){super();
}}
var b=new Ball();
Ball.run(); // 继承后静态方法也会被继承
六、ES5中类的this
除了静态属性、方法的this指向这个类,其他情况下this一般都指向当前实例化对象。
// 构造函数
function Box(){this.play();// 构造函数中this,指向new出的实例对象
}// 静态的属性、方法,类似于ES6里的静态方法、静态属性定义
Box.a=function(){console.log(this);// this -->Box
}
Box.b=3;// 写在原型下的属性、方法
Box.prototype.play=function(){console.log(this);// this 就是当前调用该方法的实例对象
}
Box.prototype.c=10; // 静态属性、方法,this指向类
console.log(Box.b);
Box.a();var box=new Box();
console.log(box); //与paly中打印的一样
// box对象没有play这个对象属性,因此就去原型链中找到最近的play方法,执行这个play方法是由box这个对象执行
// 静态属性、方法只和类有关系,与实例化的对象没有任何关系,所以不在box对象中显示。
console.dir(Box); //console.dir()可以显示一个对象的所有属性和方法
七、ES6箭头函数中的this
所有箭头函数内的this,都是当前函数外层的this指向。
var fn=()=>{};
var obj={a:()=>{console.log(this);//this--->window},b:function(){console.log(this);//this--->当前调用方},// c跟b的一样c(){console.log(this);//this--->当前调用方}
}
var obj1=obj;
obj1.a();
obj1.b();
obj1.c();
var obj={a:function(){setTimeout(()=>{// 因为本来是回调函数,this统一都会被执行window;// 但是使用了箭头函数,就会全部把这里this重定向到setTimeout外层,也就是obj。console.log(this);},100)setTimeout(function(){console.log(this);// 没有使用箭头函数,this指向window},100);}
}
obj.a();
八、call、apply、bind
当使用call,apply,bind时,都会将函数中this的指向重新指向到对应的对象。
总结
那么总结一下,都有哪些this:
全局下的this、对象中的this、回调函数中的this(事件函数中的this)、ES6类中的this、ES5中类的this、ES6箭头函数中的this、call,apply,bind中的this。
最后,其实理解了,this也就善良了。