在js中有一个东西一直折磨的我头疼,终于下定决心好好总结一波this的各种情况。
- 普通函数中的this
console.log(this);//window
function fn(){
console.log(this);
}
fn(); //window
ES5中非严格模式,普通代码全局中的this和函数中的this都指向window;
ES6中严格模式,全局中this仍然指向window,函数中this指向undefined;
- 对象中的this
var obj={
a:1,
b:function(){
console.log(this.a);
//这个this只想当前对象自身obj
//一般我们不再obj里面使用obj,因为obj中变量改变时,会发生引用改变
//而this不会因为变量引用改变而改变,就指向当前的obj
//console.log(obj.a)//有可能obj发生改变
},
c:this.a
//这个this指向对象外this的指向,一般指window
//对象还没有创建完成,this还没有生成,this就指向对象外this的指向
}
var o=obj;
obj={a:100,d:200};
o.b();//1
obj.b();//obj.b is not a function//obj指向变了
- 回调函数中的this:
1. 如果直接指向的回调函数,this指向最外层window;
2. 如果通过arguments直接使用参数指向函数,this则指向执行当前函数的arguments;
3. 如果回调函数通过call,apply,bind重新指向了新的对象,this就是指向的这个新对象 ;
var obj={
b:1,
a:function(){
setTimeout(function(){
console.log(this);
}, 2000);//直接指向回调函数中的this,this就指向Window
setTimeout(function(obj){
console.log(obj.b);
}, 2000,this);//传入了参数obj,代替了this指向,所以这里this指向obj,打印1
}
}
obj.a();
【注】只要是直接指向回调函数,不管是严格还是非严格,this就会发生改变,没有传参就会指向外面的window;
4.事件函数中this:
侦听谁,this就指向谁(只要不使用bind,不使用箭头函数)
addEventListener在IE8中this指向window;
addEventListenerIE8以上版本指向document
5.ES6类中的this:
(1) 普通方法中的this-------------被实例化对象
(2)静态方法static中的this-----当前类名
class Box{
static _instance;//单例模式
constructor(){
console.log(this);//普通方法中的this指向被实例化对象
}
play(){
console.log(this);//普通方法中的this指向被实例化对象
}
static run(){
console.log(this);
return this;
//静态方法中的this就是当前类名,也是构造函数constrcutor;
//任何的静态方法中this都是当前类;
//静态方法中无法获取到实例化对象的this;
}
//单例模式
static getInstance(){
if(!Box._instance){
Box._instance=new Box();
}
return Box._instance;
}
static plays(){
this.getInstance().play();//等于Box.getInstance().play();
或
//单例模式不管在哪里调用,或者调用几次,值都是一样
var o=this.getInstance();
var o1=this.getInstance();
console.log(o===o1);
}
}
var b=new Box();//会执行构造函数,这是构造函数中this就是这个b对象
b.play();//b对象下的方法play,因此play方法中this被指向b,谁执行play,this指向谁
console.log(Box.run()===b)//false
console.log(Box.run()===b.constrcutor)//true
(单例:借助于静态方法而完成实例化对象,不管在哪里调用都可以,每次调用的值也一样)
6.ES5 面向对象中的this
function Box(){
console.log(this);
}
//这种就相当于ES6中实例化对象,Box.prototype.play就是ES6的b.play()
Box.prototype.play=function(){
console.log(this);//this是指向执行该方法的实例化对象
}
//这种就相当于ES6中的静态方法static
//Box是对象,对象下的方法中的this指的就是该对象
Box.run=function(){
console.log(this);//Box
}
Box();//this是window或者undefined
var b=new Box();//this是实例化后的b对象
b.play();
7.箭头函数中this:this是上下文环境中this的指向(箭头函数外this的指向)
情况一:
var obj={
a:function(){
setTimeout(()=>{
console.log(this)
//this是上下文环境中this的指向(箭头函数外this的指向)
},2000)
},
};
obj.a(); //obj
情况二:
var obj={
a:function(){
document.addEventListener("click",this.clicHandler);
},
clicHandler:function(e){
setTimeout(()=>{
console.log(this);
},2000);
}
}
obj.a();//#document
情况三:
var obj={
a:function(){
console.log(this);//obj
},
b:()=>{
console.log(this);//window
}
}
obj.a();
obj.b();
情况四:
function Box(){}
//类似于ES6中的静态
Box.prototype.run=()=>{
console.log(this); //window
}
var b=new Box();
b.run();
8.call apply bind中的this:
function fn(){
console. log(this);
}
var obj={a:1}
fn.call(obj);//{a:1}//fn中this指向obj
fn. apply(obj);//{a:1}//fn中this指向obj
fn. bind(obj)();//{a:1}//fn中this指向obj
(特殊情况)
var obj={
a:function(){
function fn(){
console.log(this);//window
}
fn();
console.log(this);//window
}
}
obj.a.call(null);//如果是call apply bind 带入的是null,将会把这里的this重新指向window
以上这8种情况大概就是js中this指向的大部分情况,如果有其他情况,随时欢迎共同交流。