📘 JavaScript 中 this
、bind
与箭头函数调用过程详解
📌 本文适合你:
- 理解
() => e.run()
为什么能保持this
不变- 分清
fn = obj.method
和fn = obj.method.bind(obj)
的区别- 快速掌握
this
指向的底层原理🪧 记得收藏 + 点赞 + 关注,防止丢失这份核心知识!
🧠 一句话总结
在 JavaScript 中,
this
的值取决于函数是如何被调用的,而不是函数被定义在哪里。
🎯 场景问题引入
你是否曾经写过这样的代码:
const obj = {
name: 'Alice',
say() {
console.log(this.name)
}
}
const fn = obj.say
fn() // ❌ undefined?
💥 输出的是 undefined
!为什么?怎么解决?
那你可能听说过 bind
:
const boundFn = obj.say.bind(obj)
boundFn() // ✅ Alice
或者也有人写:
const runner = () => obj.say()
runner() // ✅ Alice
到底这些写法有什么区别?下面我们来一一解释。
🧩 this
的三种常见调用方式对比
写法 | this 是谁? | 是否推荐 | 原因 |
---|---|---|---|
obj.say() | obj | ✅ 推荐 | 正确绑定对象 |
const fn = obj.say; fn() | undefined / window | ❌ 不推荐 | this 丢失了 |
const fn = obj.say.bind(obj) | obj | ✅ 推荐 | 强制绑定 this |
const fn = () => obj.say() | obj | ✅ 推荐 | 用闭包引用对象 |
🔬 深入分析:为啥 const fn = obj.say
会丢失 this
?
因为:
const fn = obj.say
只是复制了函数本身,而没有对象调用上下文。
所以:
fn() // 没有调用者,this === undefined(严格模式)
🧠 原理:谁调用,this 就是谁
调用方式 | this 是谁 |
---|---|
obj.say() | obj |
say() | undefined (严格模式)或 window |
someFunc.call(obj) | obj |
someFunc.bind(obj) | 永远是 obj |
箭头函数 () => obj.say() | 没有 this,闭包变量决定 |
📌 bind vs 箭头函数图解对比
class Logger {
constructor(name) {
this.name = name
}
log() {
console.log(`My name is ${this.name}`)
}
}
const logger = new Logger('Alice')
✅ bind 写法
const runner = logger.log.bind(logger)
runner() // My name is Alice
调用过程图:
runner() ───► log() <-- this 被强制绑定为 logger
✅ 箭头函数写法
const runner = () => logger.log()
runner() // My name is Alice
调用过程图:
runner() ───► () => logger.log() <-- logger 是闭包变量
⚠️ 注意:箭头函数不是绑定 this!
const arrow = () => console.log(this)
arrow() // ❌ this 是外层作用域(通常不是你想要的对象)
箭头函数没有自己的 this,它会从定义它的上下文中继承 this。
🔧 应用:响应式库中的 () => e.run()
为啥能用?
例如:
const runner = () => e.run()
能正常运行,是因为:
runner()
执行时,调用的是e.run()
;e
是外部变量,闭包引用;- 所以
run()
方法里的this
正确指向e
。
不是因为箭头函数绑定了 this,而是它避开了 this 问题,直接用变量调用方法。
✅ 最终推荐
场景 | 推荐写法 |
---|---|
要传函数、this 不丢失 | .bind(obj) |
简单回调函数,不关心 this | () => obj.method() |
不要直接写 fn = obj.method | ❌ ❌ ❌ |
🧪 实战测试代码(可粘贴运行)
class Demo {
constructor(name) {
this.name = name
}
show() {
console.log('Hi, I am', this.name)
}
}
const d = new Demo('Tom')
// ❌ this 丢失
const a = d.show
a() // undefined
// ✅ bind 正确
const b = d.show.bind(d)
b() // Tom
// ✅ 箭头函数方式
const c = () => d.show()
c() // Tom
📎 结语
this
是 JS 的经典难题- 理解调用方式、避免直接赋值,是保持 this 正确的关键
bind
与箭头函数是两种常用的解决方案,各有优缺点