【JavaScript】07. this指向问题

296 阅读3分钟

这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战

this指向

01. this

(1)一般情况下

  • this 永远指向最后调用它的那个对象,谁调用就指向谁(万能口诀

  • 匿名函数的this永远指向window

  • 回调函数内的this指向的是window

    • 当将一个函数作为参数传递时,会丢失this的绑定

  • 开启严格模式后:"use strict"

    • 开启后,函数内的this将指向undefined
    • 但全局下的this还是指向window
  • 定义变量的方式不同:varletconst

    • 全局下定义的变量,只有var定义的变量才会绑定到window
    • letconst定义的变量都不会绑定在window
    var name = 'window'
    window.name = 'window'
    

(2)构造函数

  • 构造函数内的this,指向其通过new操作符,创建的实例对象

    • 注意,箭头函数是无法做构造函数的
    let cat = new Animal()
    // 构造函数内的 this 指向其创建的实例,且不会被任何方式修改
    

(3)箭头函数

  • 箭头函数没有this,它内部的this取决于它外面的第一个不是箭头函数的函数this

    • 箭头函数指向外层函数创建时this,而非执行时
    • 箭头函数会通过作用域链来查找其this
  • 字面量创建的对象不是作用域,其作用域是window,所以对象内部的箭头函数的this指向window

    • 注意,作用域只包括全局作用域和局部函数作用域
  • 构造函数创建的对象,作用域是可以理解为是这个构造函数,且这个构造函数的this是指向新建的对象的,因此this指向这个实例对象

  • 箭头函数中this一旦绑定了上下文,就不会被任何代码改变

    • 无法通过callapplybind改变
    • 但可以通过改变作用域下的this来间接修改
    function father(){
        return () => {
            return () => {
                console.log(this) // 这里的 this 是father函数的 this
            }
        }
    }
    
    let obj = {
        name: 'ruovan',
        foo1: () => {
            // 这里的this指向其外层作用域的this => window
            // obj不属于局部作用域,它是一个对象
            console.log(this.name)
        },
        foo2: function() {
            console.log(this.name) // 
            return () => {
                // 这里的 this 在函数 foo2 作用域下
                // 所以这里的 this 指向这个 obj 对象
                console.log(this.name)
            }
        }
    }
    

(4)改变指向

  • 可以通过 call、apply、bind 改变this指向

    • 使用.call()或者.apply()的函数是会直接执行
    • 使用.bind()是创建一个新的函数,需要手动调用才会执行
      • 且,通过bind函数中改变this后,其不会再被callapply修改

  • 如果call、apply、bind接收到的第一个参数是空或者null、undefined的话,则会忽略这个参数

    • 即相当于没有使用
  • forEach、map、filter函数的第二个参数也是可以显式绑定this并改变指向的

    // 通过 call、apply、bind 改变this指向
    func()
    
    // this == else
    func.call(else, arg1, arg2, ...)
    func.apply(else, [arg1, arg2, ...])
    func.bind(else)
    
    // bind 的this 不会被修改
    func.bind(else).call(other) // this == else
    
    

(5)图解this

-图来源: 点击这里查看,侵删

this.jpg


下一篇文章会简单介绍手写 call | apply | bind 方法


本人前端小菜鸡,如有不对请谅解