说说 this 的指向问题,举例讲透!
📌 点赞收藏关注不迷路!
在 JavaScript 中,this
是一个非常“灵活”的关键字,也可以说是“迷惑”的代表。
你可能会看到这些场景:
❓为什么在箭头函数里
this
和外层一样?
❓为什么 setTimeout 里的this
是window
?
❓对象方法里用this
没问题,但传出去就错了?
别急!本文将带你从原理出发,举例讲透 this 的各种指向场景,彻底搞懂它!
🧭 一、this 到底是什么?
简单来说,this
是函数在运行时自动绑定的上下文对象。它不是静态绑定,而是谁调用它,它就指向谁(大多数情况下)。
JavaScript 中 this 的绑定方式有 5 种:
- 默认绑定(普通函数)
- 隐式绑定(对象方法)
- 显式绑定(call/apply/bind)
- new 绑定(构造函数)
- 箭头函数绑定(词法作用域)
🧪 二、this 的 5 种绑定方式举例解析
1️⃣ 默认绑定(函数独立调用)
function show() {
console.log(this)
}
show() // 浏览器中是 window,严格模式下是 undefined
🔍 解释:
在非严格模式下,this
默认指向全局对象 window
。
在严格模式下,this
是 undefined
。
2️⃣ 隐式绑定(谁调用就是谁)
const user = {
name: 'Jin',
sayHi() {
console.log(this.name)
}
}
user.sayHi() // 输出 "Jin"
🔍 解释:
this
指向调用者 user
,所以输出其属性。
⚠️ 注意隐式丢失:
const fn = user.sayHi
fn() // undefined,因为此时 this 是 window
3️⃣ 显式绑定(call/apply/bind)
function greet() {
console.log(`Hello, ${this.name}`)
}
const person = { name: 'Alice' }
greet.call(person) // Hello, Alice
greet.apply(person) // Hello, Alice
const bound = greet.bind(person)
bound() // Hello, Alice
🔍 解释:
call
/apply
立即调用函数,改变this
bind
返回一个新函数,永久绑定this
4️⃣ new 绑定(构造函数)
function Animal(name) {
this.name = name
console.log(this)
}
const cat = new Animal('Tom') // this 指向新建的对象 cat
🔍 解释:
new
会创建一个新对象,并将 this
指向它,再返回这个对象。
5️⃣ 箭头函数绑定(词法作用域固定)
const user = {
name: 'Jin',
showName: function () {
const arrow = () => {
console.log(this.name)
}
arrow()
}
}
user.showName() // Jin
🔍 解释:
箭头函数不会创建自己的 this
,它会捕获定义它时的外层 this
,所以这里是 user
。
⚠️ 三、this 的常见坑位总结
❗setTimeout 中的 this
const obj = {
name: 'Jin',
say() {
setTimeout(function () {
console.log(this.name) // undefined
}, 100)
}
}
obj.say()
✅ 解决方案:用箭头函数
setTimeout(() => {
console.log(this.name) // 正确打印 Jin
}, 100)
❗事件监听中的 this
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
console.log(this) // this 是当前 button 元素
})
✅ 但如果用箭头函数:
btn.addEventListener('click', () => {
console.log(this) // this 是外层作用域,可能是 window
})
❗Vue 中的 this(2.x 和 3.x 有区别)
export default {
data() {
return { msg: 'Hello' }
},
mounted() {
console.log(this.msg) // 正常输出
}
}
⚠️ 但 Composition API 中:
setup() {
console.log(this) // undefined,不能再用 this
}
📌 所以 Vue 3 中推荐使用 ref
、reactive
代替 this
逻辑。
🧠 四、判断 this 的 4 步法则(记牢!)
当你搞不清某个函数的 this
,请按这个顺序判断:
- 是否使用了
new
?👉 则绑定到新对象 - 是否使用
bind
/call
/apply
?👉 显式绑定 - 是否是对象的方法调用?👉 隐式绑定
- 都不是?👉 默认绑定(严格模式下是
undefined
,否则是window
)
例题演练:
const foo = {
name: 'Foo',
bar() {
return () => {
console.log(this.name)
}
}
}
const fn = foo.bar()
fn() // Foo,因为箭头函数绑定的是 bar 的 this,即 foo
🎯五、总结:掌握 this 是理解 JS 的关键
类型 | 示例 | 指向 |
---|---|---|
默认绑定 | 独立函数调用 | window 或 undefined |
隐式绑定 | obj.fn() | obj |
显式绑定 | fn.call(obj) | obj |
new 绑定 | new Fn() | 新对象 |
箭头函数 | ()=>this | 外层作用域的 this |
牢牢记住:this 是执行时绑定的,不是定义时决定的!
✅最后说一句
如果你觉得这篇文章让你对 this
有了更深刻的理解,不妨点个 点赞 + 收藏 + 关注,支持一下创作吧!
下一篇我们可以写:
📦《彻底搞懂 JavaScript 闭包的本质和应用场景》
欢迎留言想看的话题,继续发标题我来写 👇