关于this

17 阅读2分钟

this的5中绑定规则

  1. 默认绑定

    当函数独立调用时,this默认指向全局(window)

const showThis = () => {
  console.log(this) // 返回window
}
showThis() // 返回window
  1. 隐式绑定

当函数作为对象的方法调用时,this指向调用该方法的对象

let obj = {
  name: 'test',
  sayName: function () {
    console.log(this) // 指向obj
    console.log(this.name)
  },
}
obj.sayName() // 输出test
// 常见陷阱:方法赋值给变量
const greet = user.sayHello
greet() // "Hello, undefined" - this 丢失,指向全局
  1. 显示绑定

使用apply,bind,call进行绑定,强制把this绑定(这里只用apply进行绑定测试)

let obj = {
  name: 'test',
}
function sayName() {
  console.log(this) // 默认指向window
  console.log(this.name)
}
sayName() // 会输出undefined,因为这里函数内部的this指向window
// 这里说一下,我在运行的时候发现这里不会输出undefined,而是输出了空字符串,
// 原因是我在浏览器环境下运行的,而浏览器的window对象有一个name属性,默认值是空字符串
// 所以这里输出的是空字符串,如果在node环境下运行的话,这里会输出undefined
sayName.apply(obj) // 会输出test,这里把sayName这个函数的this给绑定到obj上了
  1. new 绑定

使用 new 调用构造函数时,this 指向新创建的对象

function Person(name) {
  this.name = name
  this.sayName = function () {
    console.log(this.name)
  }
}
let test = new Person('test')
test.sayName() // 会输出test
  1. 箭头函数

箭头函数比较特殊,他没有this,所以他需要向上一层找,也就是继承外层作用域的this

let obj = {
  name: 'test',
  sayName: () => {
    console.log(this) // 指向window
    console.log(this.name) // 输出空字符串
  },
}
obj.sayName()

各种场景下的this

  1. Dom事件处理函数
button.addEventListener('click', function () {
  console.log(this) // 指向 button 元素
})
// 箭头函数不绑定自己的 this
button.addEventListener('click', () => {
  console.log(this) // 指向定义时的上下文
})
  1. setTimeout / setInterval
const obj = {
  name: '定时器示例',
  timeoutFunc: function () {
    setTimeout(function () {
      console.log(this.name) // 指向 Window/global
    }, 1000)
  },
  timeoutArrow: function () {
    setTimeout(() => {
      console.log(this.name) // 继承外层 this,指向 obj
    }, 1000)
  },
}

this的优先级

new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定

箭头函数忽略以上所有规则,继承外层作用域