js中的this指向

概述

this主要分为以下几种

  1. 非严格模式下,全局中this指向window
  2. 对象中的this : 属性中的this指向外层this ;方法中的this指向该对象
  3. 回调函数中的this指向window
  4. 事件回调函数中的this被修改成e.currentTarget(被侦听的对象)
  5. 箭头函数中的this指向指当前函数外
  6. ES6类中的this指向实例化对象 ,静态方法或者属性指向该类名
  7. ES5中的类中的this 原型上的属性和方法指向实例化对象,静态指向类名
  8. call apply bind 的this指向第一个参数

1-----全局中this指向window

非严格模式下,下面的this都是window

console.log(this);//window
 
function abc(){
    console.log(this);//window
}

2-----对象中的this

  • 对象中属性的this,指的是外层的this,因为这时候对象还没有创建完成
  • 对象中的方法是在对象执行完成以后才调用的.所以this就是当前对象
   var a=10;
   var obj1={
       a:100,
       c:this.a,//10  this是window  这时候对象还没有创建完成,指向外层的this,即为window
       init:function(){
        //    this
                var obj={
	                a:1,
	                c:this.a,// 100   属性描述this是obj1
	                b:function(){
	                    console.log(this.a);//1    方法中使用this,指向该对象obj
	                }
           		 }
           		 obj.b();
           		 console.log(obj.c)//100
       }
   }
   obj1.init();
var obj = {
   a: 1,
   c: this.a,//属性描述this为window
   b: function () {
       // 方法中使用this
       console.log(this.a); //1  this为obj   
       this.d();//this为obj  
       // obj.d();//不能写出obj.d();因为obj可能会更改
   },
   d:function(){
       console.log("aaa");
   }
} 
obj.b();

3-------回调函数中的this指向window

function a(fn){
     fn();
 }
function abc(){
     console.log(this);//window  这个函数是回调函数
 }
 a(abc);

var obj={
    a:function(){
        console.log(this);//obj
        var arr=[1,2,3];
        arr.forEach(function(){
            console.log(this);//window 这个forEach中的函数是回调函数
        })
        this.b(this.c);
        this.b(abc);
    },
    b:function(fn){
        fn();
        console.log(this,"_____");//对象中的方法中的this指向该对象 obj
    },
    c:function(){
        console.log(this);//window  这个函数是回调函数
    }
}

obj.a();
	var obj={
            a:function(fn){
                fn();
            },
            b:function(){
                // 如果直接执行obj.b() 这里的this应该是obj对象
                // 如果通过上面a方法回调执行当前b的时候,this被重定向到window
                console.log(this);
            }
        }
     obj.a(obj.b);

所有的函数一旦被写在一个方法中,这个函数就是匿名的回调函数,在该函数中this指向window…比如:forEach()、filter()、reduce()、map()、some()、every()、promise…中函数都是回调函数,它们的 this 也都指向 window。

 var obj = {
       a: function () {
           setTimeout(function () {
               console.log(this)//window
           }, 100);
           // 所有的函数一旦被写在一个方法中,这个函数就是匿名的回调函数,在该函数中this指向window
           setInterval(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
           })
       }
   }

4------事件回调函数中的this被修改成e.currentTarget(被侦听的对象)

    // 事件侦听
    document.addEventListener("click",clickHandler);
    // 事件回调函数
    function clickHandler(e){
    console.log(this)// 事件回调函数中this都是被侦听的对象  this--->e.currentTarget
    }

对象中的事件函数
第一次打印obj 点击打印document

var obj={
     a:function(){
         document.addEventListener("click",this.b);
         this.b();//对象里方法中的this为该对象obj
     },
     b:function(e){
         // 因为b函数是事件侦听的回调函数,因此这里this指向事件侦听的对象,也就是document
         console.log(this);
     }
 }
 obj.a();

5-----箭头函数中的this

  • 所有箭头函数内的this都是指当前函数外的this指向
  • 当箭头函数和回调函数一起时,箭头函数改变了this指向,将指向箭头函数外层的this
  var obj={
      a:function(){
          var arr=[1,2,3];
          arr.forEach(function(){
              console.log(this);//遵从于回调函数的this指向。window
              // this.d();//报错,window中没有方法d
          });
          arr.forEach(item=>{
              console.log(this)//obj
              // this 因为使用了箭头函数,就会忽略了回调函数的this指向
          })
          document.addEventListener("click",this.clickHandler);
          document.addEventListener("click",e=>{
              console.log(this)//obj
              // this 因为使用箭头函数,就会忽略了事件函数中this指向
              this.d();
          })
      },
      clickHandler:function(e){
          console.log(this)//遵从于事件函数中this---e.currentTarget
          // this.d();//报错  this为document事件对象
      },
      d:function(){
          console.log(this)
      },
      e:function(){
            setTimeout(()=>{
                // 因为本来是回调函数,this统一都会被指向window
                // 但是使用了箭头函数,就会全部把这里this指向setTimeout外的this指向,也就是obj
                console.log(this);
            },100)
        }
  }
  obj.a();

6------ES6类中的this指向实例化对象 ,静态方法或者属性指向该类名

  • 类中的this是指实例化的对象,谁调用的属性和方法,this就是谁
  • 静态属性或者方法,this指向都会被设置为当前的类名Box(对于面向对象语言来说,一般在静态属性和方法中不允许使用this这个概念)
  • 如果类被继承,继承后静态方法也会被继承
		class Box{
            // ES7后才有的
            // 这里的内容是constructor执行后赋值
            b=3;
            // a=this.b;
            static b=20;
            /static a=this.b;
            //一旦被设为静态属性,this指向都会被设置为当前的类名Box 因为设置了static b=20 所以a是20
            constructor(){
                this.b=3;
                this.a=this.b;
                //Box.b=20;
                //Box.a=Box.b;早期的静态属性写法,相当于static 
            }
            play(){
                // 这里的this都是实例化的对象
                console.log(this.a);
            }

            static run(){
                console.log(this);
                // this
                // 因为使用static定义的方法,this指向为当前类名Box
                // 对于面向对象语言来说,一般在静态属性和方法中不允许使用this这个概念
            }
           
        }
        var b=new Box();

如果类被继承,继承后静态方法也会被继承

//Ball继承Box
	class Ball extends Box{
            constructor(){
                super();
            }
          
        }
	var b=new Ball();
     Ball.run();//继承后静态方法也会被继承

案例

export default class Rect{
    elem;
    bool=false;
    speed=2;
    x=0;
    constructor(){
        this.elem=this.creatElement()//this指向该类,调用该类的方法直接用this
    }
    //创建元素
    creatElement(){
        if(this.elem) return this.elem;
       let div= document.createElement('div')
       Object.assign(div.style,{
           width:'50px',
           height:'50px',
           background:'red',
           position:"absolute",
           left:"0px"
       })
       div.addEventListener('click',e=>this.clickHandler(e))
       //事件回调函数中this是该事件,这里需要调用该类中的方法clickHandler(),所以需要用箭头函数改变this指向为该类
       return div
    }
    //添加到父元素
    appendElem(parent){
        parent.appendChild(this.elem)
    }

    //添加点击事件
    clickHandler(e){
        this.bool=!this.bool;//使用类中的属性,直接用this.属性就可以
    }

    //移动
    move(){
        if(!this.bool) return;
        this.x+=this.speed;
        console.log(this.x)
        this.elem.style.left=this.x+'px'
    }
}

7----ES5中的类 原型上的属性和方法指向实例化对象,静态指向类名

  • ES5中没有类,借用原型的概念实现类
  • 静态方法只和类有关系,与实例化的对象没有任何关系
  • b对象没有play这个对象属性,因此就去原型链中找到最近的play方法
function Box(){
//相当于es6中的constructor()
      this.play();
      // 构造函数中this,new出的对象-->b
  }
  Box.a=function(){
      // 这个方法类似于ES6的静态方法
      // this  -->Box
  }
  Box.b=3;//和ES6静态定义属性一样

  Box.prototype.play=function(){
      // this  就是当前调用该方法的实例对象 -->b
  }
  Box.prototype.c=10; 
  console.log(Box.b)//3 获取静态属性b
  
  var b=new Box();
  b.play();//b对象没有play这个对象属性,因此就去原型链中找到最近的play方法,执行这个play方法是由b这个对象执行,因此play中的this就是b

如下图 b.proto 等同于Box.prototype
在这里插入图片描述

8----call apply bind 的this指向第一个参数

  • 当使用call,apply,bind都会将函数中this的指向重新指向到对应的对象
  • call 执行函数,并且将该函数中this指向call的第一个参数,call的第二个参数开始一一带入所有参数
  • apply 执行函数,并且将该函数中this指向call的第一个参数,apply的第二个参数是这个函数的所有参数组成数组
  • bind执行函数,并且将函数中的this指向bind的第一个参数
  • 当第一个参数为空或者null时,this指向window
function fn(_a,_b){
        this.a=_a;//this指obj
        this.b=_b;
    }
 var obj={};
 //fn.call(obj,3,5);
 fn.apply(obj,[3,5]);
 console.log(obj);//{a:3,b:20}

bind

function fn1(fn){
     fn(3);
 }
 function fn2(_a){
     this.a=_a;//this是指obj
 }
 var obj={};
 fn1(fn2.bind(obj));//把fn2函数中的this指向obj,并且返回这个被指向this后新的函数
 console.log(obj);//{a:3}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡肖一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值