在开始之前,我们先了解一个概念,上下文。
上下文分为:
- 全局上下文也就是window
- 函数上下文
好的了解了这些,我们还需要知道一个问题,this 是在函数运行时被绑定的,并且在执行期间不可以被赋值,接下来进入主题
1. this 在标准函数中的指向问题
- this 绑定的是引用该函数上下文的对象,或者 全局上下文 window(在严格模式下为undefiend)
如以下代码所示:
① 通过对象调用函数:根据结论,this 绑定的是引用该函数上下文的对象,因此指向obj,所以输出为Jon
② 直接调用: 根据结论,this绑定全局上下文 window,因此输出 Tom
window.name = 'Tom'
let obj = {
name: 'Jon',
getName() {
return this.name;
}
}
console.log(obj.getName()); // Jon
let getName_ = obj.getName;
console.log(getName_()) // Tom
2. this 在箭头函数中的指向问题
- 箭头函数中并没有 this,他引用的是其父上下文所绑定的 this
上下文有函数上下文和全局对象上下文,而该箭头函数的父上下文为全局对象上下文 window,因此无论以哪种方式调用,其this 总是指向 window,从而输出 Tom
window.name = 'Tom'
let obj = {
name: 'Jon',
getName:() =>{
return this.name;
}
}
console.log(obj.getName()); // Tom
let getName_ = obj.getName;
console.log(getName_()) // Tom
3. 定时器中的 this 指向
- 定时器中的 this 永远指向 window 全局对象
① 首先来说使用匿名函数的情况
根据结论,其父上下文是 setTimeout 这个函数上下文,而该函数又是 window 对象下的一个函数,无论是作为普通函数调用,还是以 window.setTimeout 的形式调用,其 this 总是指向window
② 再看普通函数的调用情况:
根据结论,普通函数中的 this 指向引用该函数上下文的对象,或 window,显然这里指向window
setTimeout(()=>{
console.log(this)
},100)
setTimeout(function(){
console.log(this)
},100)
③ 再看一种特殊情况
乍一看,obj.fun ,这个 this 指向的是obj ,为什么是 window 呢?我们来分析一下,setTimeout 是一个函数,因此 obj.fun 作为参数,相当与赋值给一个变量,然后调用,就相当于是作为普通函数调用
let obj = {
fun(){
console.log(this)
}
}
setTimeout(obj.fun,200) // window
我们来展开写以下:
这样我们很容易看出,该this 指向的是全局上下文 window
let fn = obj.fun;
setTimeout(fn,200)
4. 监听事件中的 this 指向
这个跟原理相违背,暂时也不太懂,只能死记,查阅很多资料也没有结果,若有大佬明白原理,希望评论赐教,谢谢!!!
document.querySelector('#test').addEventListener('click', ()=>{
console.log(this) // window
})
document.querySelector('#test').addEventListener('click', function(){
console.log(this) // dom 节点
})