This的指向

102 阅读2分钟

一、是什么

this这个关键字代表的值为当前函数执行的上下文,大多数情况下this的值取决于函数的调用方式。

this是在运行时进行绑定的,只能在函数内部使用。

二、绑定规则

  • 默认绑定

  • 在函数体中,非显式或隐式地调用函数时,在严格模式下,函数内的this会被绑定到undefined上,在非严格模式下则会被绑定到全局对象window/global上。

  •   function f1(){
        console.log(this)
      }
      function f2(){
        'use strict'
        console.log(this)
      }
      f1() // window
      f2() // undefined
    
  • 隐式绑定

  • 一般通过上下文对象调用函数时,函数体内的this会被绑定到该对象上。

  •   function f1(){
        console.log(this.a)
      }
      var obj = {
        a: 1;
        fn: f1
      }
      obj.fn() // 1
      // 陷阱1
      var f2 = obj.fn
      f2() // undefined,这里f2()等价window.f2()
    
  • new绑定

  • 一般使用new方法调用构造函数时,构造函数内的this会被绑定到新创建的对象即实例对象上。

  •   function F() {
        this.a = 1
      }
      var f = new F()
      f.a // 1
      // 特殊情况
      function F1() {
        this.a = 1
        return {}
      }
      var f1 = new F1()
      f1.a // undefined 原因是构造函数中如果return一个对象,则this指向该对象
      
      function F2() {
        this.a = 1
        return 1
      }
      var f2 = new F2()
      f2.a // 1 原因是构造函数如果return一个基本类型的值,那么this仍指向实例。
    
  • 显式绑定

  • 一般通过call/apply/bind方法显示调用函数时,函数体内的this会被绑定到指定参数的对象上。

  • 箭头函数

  • 在箭头函数中,this指向其所属函数的this或全局作用域。

  •   var f = {
        fn: () => {
          console.log(this)
        }}
      f.fn() // window 因为fn箭头函数并不在函数内,因此指向全局作用域
      var f1 = {
        a: 1,
        fn: function() {
          const f = () => {
            console.log(this)
          }
          f()
        }}
      f1.fn() // {a: 1, fn:function(){}} 箭头函数指向fn函数的this
      var f2 = f1.fn
      f2() // window 此时fn函数的this指向window
    

三、优先级

  • 显式VS隐式

  •   var f = {
        a: 1,
        fn: function(){
          console.log(this.a)
        }
      }
      var obj = {a: 2}
      f.fn() // 1
      f.fn.call(obj) // 2 
      显式 > 隐式
    
  • newVS显示

  •   function fn(a) {
        this.a = a
      }
      var obj = {}
      var F = fn.bind(obj) // F的this指向obj
      F(1) // obj.a = 1
      var f = new F(2) // f的this指向了F的实例, f.a === 2
      new > 显式
    
  • 箭头VSnew

  • 由于箭头函数无法作为构造函数,无法比较。

  • 箭头VS显式

  •   function fn() {
        return () => {
          console.log(this.a)
        }
      }
      const obj1 = {a: 1}
      const obj2 = {a: 2}
      const f1 = fn.call(obj1) // 此时箭头函数所属函数的this绑定在obj1
      f1() // 1
      f1.call(obj2) // 1 箭头函数的this绑定无法被修改
      箭头 > 显式
    

综上得出:new绑定/箭头函数 > 显式绑定 > 隐式绑定 > 默认绑定

参考资料: