this 指向非常简单,10分钟就能搞懂!
作用
this 常用于在代码执行的环境中快速指向某个对象,从而进行一些数据相关的便捷操作
分析
浏览器环境中
1. 全局作用域下
this 默认指向 window 对象
console.log(this) // window
function sayThis() {
console.log(this) // window
}
sayThis()
function aa() {
console.log(this) //window
bb()
}
function bb() {
console.log(this) //window
}
function cc() {
console.log(this) // window
}
aa()
2. 隐式绑定
this 指向调用者
const person = {
sayThis: function() {
console.log(this) // person
}
}
person.sayThis()
再来看 隐式绑定 的另外一种情况
function sayThis() {
console.log(this)
}
const personA = {
sayThis
}
const personB = {
sayThis
}
personA.sayThis() // this -> personA
personB.sayThis() // this -> personB
说的直白一点,谁离我最近并调用了我,我内部的 this 就指向谁
3. 显示绑定
利用 apply、call、bind 可以将 this 指向更改为被显示绑定的那个对象
function sayThis() {
console.log(this)
}
const personA = {}
const personB = {}
sayThis.apply(personA) // this -> personA
sayThis.call(personA) // this -> personA
sayThis.apply(personB) // this -> personB
sayThis.call(personB) // this -> personB
和 隐式绑定 的例子区别在于:我当前对象上没有任何方法可以去访问 this ,但是我可以通过 显示绑定 去借用别人的方法来访问 this,此时 this 指向会更改为显示绑定的那个对象
4. 实例化
构造函数中 this 指向被实例化的那个对象
function Person() {
console.log(this) // p
}
const p = new Person()
5. 箭头函数
箭头函数内部默认 没有绑定 this
当你尝试在箭头函数中去访问 this 时,如果当前环境中没有 this,会根据其所在的上下文去查找最近可用的 this
const sayThis = () => {
console.log(this) // window
}
sayThis()
sayThis() 中默认没有 this ,但距离它最近的 this 也就是 全局作用域 中的 this,因此打印 window
const person = {
sayThis: function() {
console.log(this) // person
setTimeout(function() {
console.log(this) // window
})
}
}
person.sayThis()
需要注意的是 setTimeout 中的回调仍然是一个普通函数,因此 this 默认指向 window,如果要在其中访问到 person 对象,通常我们会声明一个变量用于保存 this 的值
const person = {
sayThis: function() {
console.log(this) // person
const _this = this
setTimeout(function() {
console.log(_this) // person
})
}
}
person.sayThis()
或者利用箭头函数本身不绑定 this 但会根据上下来查找的特性将其改造
const person = {
name: 'person',
sayThis: function() {
console.log(this) // person
setTimeout(() => {
console.log(this) // person
})
}
}
person.sayThis()
这里的 sayThis() 可不能更改为箭头函数,否则两个箭头函数都没有绑定 this 指向,最终会打印 window
顺带一提,在 es6 中, sayThis:function(){} 通常会简写为 sayThis(){},后者作为前者的增强写法(语法糖形式),默认是存在 this 绑定的,这一点需要和箭头函数区别开来