this的5中绑定规则
-
默认绑定
当函数独立调用时,this默认指向全局(window)
const showThis = () => {
console.log(this) // 返回window
}
showThis() // 返回window
- 隐式绑定
当函数作为对象的方法调用时,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 丢失,指向全局
- 显示绑定
使用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上了
- new 绑定
使用 new 调用构造函数时,this 指向新创建的对象
function Person(name) {
this.name = name
this.sayName = function () {
console.log(this.name)
}
}
let test = new Person('test')
test.sayName() // 会输出test
- 箭头函数
箭头函数比较特殊,他没有this,所以他需要向上一层找,也就是继承外层作用域的this
let obj = {
name: 'test',
sayName: () => {
console.log(this) // 指向window
console.log(this.name) // 输出空字符串
},
}
obj.sayName()
各种场景下的this
- Dom事件处理函数
button.addEventListener('click', function () {
console.log(this) // 指向 button 元素
})
// 箭头函数不绑定自己的 this
button.addEventListener('click', () => {
console.log(this) // 指向定义时的上下文
})
- 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 绑定 > 显式绑定 > 隐式绑定 > 默认绑定
箭头函数忽略以上所有规则,继承外层作用域