JavaScript用“function”关键词定义的函数中的this和谁调用这个函数有关,与他在哪里调用,如何定义无关。常见的由5种情况:
- 普通调用:this指向window
- 对象调用:this指向调用的对象,也就是"."前面的对象
- 定时器处理函数(作为参数传递给定时器,作为定时器的处理函数):指向window
- 事件执行函数(作为参数传递给addEventListener等,作为事件的处理函数):指向事件绑定的对象
- 自执行函数:指向window
下面分析几个实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
div {
width: 200px;
height: 300px;
background-color: pink;
}
</style>
</head>
<body>
<div>
<button>请点击</button>
</div>
<script>
function fn() {
console.log(this)
}
let obj = {
f: fn,
f2: function () {
console.log("我是obj内部定义的函数", this)
console.log(this.name)
console.log("在obj的函数里面调用fn")
fn() // 由window调用,虽然在obj的定义当中,但是指向window
},
name: "我是obj对象"
}
// 这两个函数虽然指向相同的函数空间,但是调用它的对象不同,this的指向也不同
fn() // 普通调用,this指向window
obj.f() // 对象调用,this指向调用函数的对象
// 定时器调用,函数作为setTimeout的参数,函数由window调用,所以this指向window
setTimeout(fn, 0)
// 注意下面两种obj.f2的不同
// 1. obj.f2: 自己作为一个对象传递出去,实际调用的不是obj
// 2. obj.f2(): 函数被调用,this指向obj
setTimeout(obj.f2, 0) // obj.f2自己作为事件处理函数,由window调用
setTimeout(function () {
console.log("在定时器内部,通过对象调用函数")
obj.f2()
}, 0)
// 事件处理函数调用,this指向绑定的对象
const div = document.querySelector('div')
div.addEventListener('click', function () {
console.log("function事件处理函数", this)
})
// 箭头函数,指向函数外部空间中的this
const button = document.querySelector('button')
button.addEventListener('click', () => {
console.log("箭头函数", this)
});
</script>
</body>
</html>
如果使用了箭头函数,情况就简单了,箭头函数的this指向函数外部空间中的this,实际编程的时候,为了避免this指向的错误,尽量使用箭头函数。