js中this的五种情况

555 阅读3分钟

由于很多小白对this指向情况概念很模糊,本文将围绕js中的this的五种情况展开分析。

  • 事件绑定
  • 普通函数执行
  • 构造函数执行
  • 箭头函数
  • call、apply、bind

1、情况一:事件绑定

this:给元素的某个事件行为绑定方法,事件触发,方法执行,此时方法中的 this一般都是当前元素本身

1.1 DOM0事件绑定

    <button id="btn">点我</button>

    <script>
        
     btn.onclick=function anonymous(){
  console.log(this);   //<button id="btn">点我</button>
  
     }
    </script>

1.2 DOM2事件绑定

addEventListener不兼容IE 6/7/8

  方法一: <button id="btn">点我</button>

    <script>
     btn.addEventListener('click',function anonymous(){
   console.log(this); =>元素
   
     },false)
     
  方法二:   //  兼容iE 6/7/8 DOM2事件绑定
     btn.attachEvent('onclick',function anonymous(){
      console.log(this);//this指向window
  
     })
    </script>
  • 特殊情况:如下图
function fn(){
         console.log(this);
         
     }
     btn.onclick=fn.bind(window)

fn.bind(window)首先会返回一个匿名函数(AM),把AM绑定给事件,点击触发执行AM,AM中的this是元素,但是会在AM中执行fn,fn中的this是预先指定的window

2、情况二:普通函数执行

'点'前面是谁this就是谁 普通函数执行,它里面的this是谁,取决于方法执行前面是否有"点" 有的话,“点”前面是谁this就是谁,没有this指向window(严格模式下是undefined

   <script>
        function fn(){
            console.log(this);
        }
        let obj={
            name:'OBJ',
            fn:fn 
        }
        //  fn();      //=>window
        //  obj.fn()  //=>OBJ 
         console.log(obj.hasOwnProperty('name') );   //hasOwnProperty方法中this:obj  ture
         
         console.log(obj.__proto__.hasOwnProperty('name'));//hasOwnProperty方法中this:obj.proto(Object.prototype)  false
         
         console.log(Object.prototype.hasOwnProperty.call(obj,'name')); //  等价于 obj.hasOwnProperty('name')  ture
          </script>
  • hasOwnProperty用来检测某个属性名是否属于当前对象的私有属性

  • in是用来检测是否为其属性(不论私有还是共有)

console.log(obj.hasOwnProperty('name'));
console.log(obj.hasOwnProperty('toString'));
console.log('toString' in obj);

3、情况三:构造函数执行(new xxx)

函数中的this是当前类的实列

<script>
        function Fn(){
            console.log(this);
            //this.xxx=xxx是给当前实列设置私有属性
        }
       let f= new Fn;
    </script>

4、情况四:箭头函数

  • 箭头函数中没有自身的this,所用到的this都是其上下文的this

  • 箭头函数没有的东西很多:

    • 1.没有prototype(也就是没有构造器),所以不能被new执行
    • 2.它没有arguments实参集合(可以基于...args剩余运算符获取)
      <script>
          let obj={
              fn:()=>{
                  console.log(this);
                  //this:window
              }
          }
          obj.fn();
      </script>
    

    箭头函数里this不一定是window

    话不多说,看下面的代码:

      <script>
       let obj={
              name:'OBJ',
              fn:function(){
            // console.log(this); //=>obj
            return ()=>{
                console.log(this); //=>obj    
            }      
           }
          }
          let ff=obj.fn()
      </script>
    

5、情况五:、call、apply、bind

this:基于call/apply/bind可以改变函数中this的指向(强行改变)

5.1call/apply

  • 第一个参数就是this指向,写谁就是谁(特殊:非严格模式下,传递null/undfined指向的是window
  func.call([context],10,20)
  • 唯一区别:执行函数的参数方式有区别,call是一个个传递,apply是把需要传递的参数放在数组中整体传递
 func.apply([context],[10,20])
   <script>
 let obj={
            fn(x,y){
                console.log(this,x,y);
            }
        }
        obj.fn.call('',10,20);     //String 10 20
        obj.fn.apply('',[10,20]);  //String 10 20
           </script>

5.2 bind

call/apply都是改变this的同时直接把函数执行了,而bind不是立即执行函数,属于预先改变this和传递一些内容 【this的第五种情况写在下一章】