在前端开发中,函数的this老是让人摸不着头脑,列举常见的this出现的场景,方便大家记忆学习,以下例子都是在浏览器环境下
执行环境
全局上下文中,this的指向全局对象
console.log(this === window) // true(浏览器环境)
函数上下文中,this的值取决于函数的调用方式, 在严格模式下,如果进入执行环境时没有设置 this 的值,this 会保持为 undefined
类上下文this在 类 中的表现与在函数中类似,因为类本质上也是函数,注意:在类的构造函数中,this 是一个常规对象。类中所有非静态的方法都会被添加到 this 的原型中
使用场景
1.call/apply
this将绑定到call/apply的第一个参数,在非严格模式下使用 call 和 apply 时,如果用作 this 的值不是对象,则会被尝试转换为对象, null 和 undefined 被转换为全局对象
const obj = { a: 1 }
function testFn (paramA, paramB) {
console.log(this.a, paramA, paramB)
}
testFn.call(obj, 2, 3) // 1 2 3
testFn.apply(obj, [2, 3]) // 1 2 3
call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组
2.bind
this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的,而其余参数将作为新函数的参数(偏函数),供调用时使用
const obj = { a: 1 }
function testFn (paramA, paramB) {
console.log(this.a, paramA, paramB)
}
const bundle = testFn.bind(obj, 2, 3)
bundle() // 1 2 3
3.箭头函数
在箭头函数中使用this值与封闭词法环境的this保持一致,全局环境中指向全局对象
备注:箭头函数没有自己的this,arguments,super和new.target
setTimeout(() => {
console.log(this) // this指向为window
})
function Test () {
this.a = 1
setTimeout(() => {
console.log(this.a) // this指向 Test
})
}
const t = new Test()
4.作为对象的方法
this的值将指向调用方法的对象
const obj = {
a: 1,
getA () {
console.log(this.a)
return this.a
}
}
obj.getA() // 1
5.原型链中的this
如果该方法存在于对象的原型链上,this的值将指向调用函数的对象
function Test () {
this.a = 1
}
Test.prototype.getA = function () {
console.log(this.a)
return this.a
}
const t = new Test()
t.getA() // 1
6.getter与setter中的this
this的值将指向获取或者设置属性的对象
let a = {
a: 1,
get name () {
return this.a
}
}
Object.defineProperty(a, 'b', {
get () {
return this.a
},
set (val) {
this.b = val
}
})
7.作为构造函数
this的值指向正在构造的新对象
function Test () {
this.a = 1
console.log(this.a) // this指向 t
}
const t = new Test()
8.作为一个DOM事件处理函数
this的值指向currentTarget,注意区分currentTarget和target的区别,currentTarget是指向事件绑定的元素,target是事件触发的元素
// index.html文件
<button id="btn">click</button>
// js代码
const btnEle = document.querySelector('#btn')
function onClick (e) {
console.log(e.currentTarget === this) // true
}
btnEle.addEventListener('click',onClick)
9.作为内联事件处理函数
this的值指向监听器所在的DOM元素,没有设置内部函数的 this,它指向 window 对象
// index.html
<button id="btn" onclick="onClick()">test</button>
// index.js
function onClick () {
console.log(this) // window 没有设置内部函数的 this,所以它指向 global/window 对象
}
// this指向 button元素
<button onclick="alert(this.tagName.toLowerCase());"></button>
总结
绝大多数情况下,函数的调用方式决定了this的值(运行时绑定this的值),每次函数调用时,this的值也有可能不一样。当然了我们可以使用call/apply和 bind指定函数的this值,而不需要考虑函数的调用方式