JavaScript 中 `this`、`bind` 与箭头函数调用过程详解

📘 JavaScript 中 thisbind 与箭头函数调用过程详解

📌 本文适合你:

  • 理解 () => e.run() 为什么能保持 this 不变
  • 分清 fn = obj.methodfn = 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 与箭头函数是两种常用的解决方案,各有优缺点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值