JavaScript 中 call、apply、bind 的区别

先理解核心:它们都是干啥的?

想象你借了一本书(函数),但你想让别人(指定对象)来读这本书的某个章节(执行函数)。

  • call:现在就让人读,你一个个告诉他读哪几页

  • apply:现在就让人读,你把页数写在一张纸条上交给他

  • bind:不急着读,先告诉他要读哪几页,给他一张"读书券",以后随时可以让他读


我的"顿悟三连"

第一层困惑:它们好像都一样?

刚学的时候,看代码:

javascript 复制代码
fn.call(obj, 1, 2, 3)
fn.apply(obj, [1, 2, 3])
fn.bind(obj, 1, 2, 3)()

内心OS:不就是参数写法不一样吗?搞这么复杂干嘛!

第二层顿悟:原来是"立即执行"和"稍后执行"的区别

直到有一次写事件监听:

javascript 复制代码
// 错误示范 ❌
button.onclick = user.sayHello.call(user);  
// 页面加载完立刻就执行了!不是我想要的

// 正确示范 ✅
button.onclick = user.sayHello.bind(user);
// 点击时才执行,完美!

这一刻我懂了:bind 是"发号施令"但不立即行动,call/apply 是"立刻执行"。

第三层顿悟:什么时候用 call,什么时候用 apply?

有次写代码找数组最大值:

javascript

javascript 复制代码
// 用 apply 多优雅
Math.max.apply(null, [1, 2, 3, 4, 5]);

// 用 call 就尴尬了
Math.max.call(null, 1, 2, 3, 4, 5); // 也行,但参数多时累死

这一刻我悟了

  • 已有数组 → apply(直接把数组扔进去)

  • 参数明确 → call(看得清楚,不用转数组)


终极对比表(我背了这一张就够了)

维度 call apply bind
执行时机 立即执行 立即执行 返回新函数,不执行
参数形式 逐个传入 a,b,c 数组传入 [a,b,c] 逐个传入,可分批传
返回值 函数结果 函数结果 新函数
经典场景 继承父类属性 找数组最大/小值 事件绑定、setTimeout
记忆口诀 C all = Comma(逗号) A pply = Array(数组) B ind = Back(稍后)

面试官最爱问的"坑"

Q:bind 之后还能改 this 吗?

javascript 复制代码
const obj = { name: 'obj' };
const obj2 = { name: 'obj2' };

function test() { console.log(this.name); }

const bound = test.bind(obj);
bound(); // 'obj'
bound.call(obj2); // 还是 'obj'!bind 绑定了就改不了了

Q:箭头函数能用 call/apply/bind 吗?

javascript 复制代码
const arrow = () => { console.log(this); };

// 没用!箭头函数的 this 是定义时就定死的
arrow.call({ name: 'test' }); // this 还是原来的

Q:手写一个 bind 看看?

javascript 复制代码
Function.prototype.myBind = function(context, ...bindArgs) {
  const fn = this;
  return function(...callArgs) {
    return fn.apply(context, [...bindArgs, ...callArgs]);
  };
};

我的最终心得

不要死记硬背,要理解设计意图

  • call:适合参数数量固定,想写得直观时

  • apply:适合参数已经在数组里,或者数量不确定时

  • bind:适合不急着执行,或者要传给事件监听、定时器时

最常用的反而是 apply (处理数组)和 bind(处理 this 指向),call 用得最少。但面试爱问区别,所以三个都得懂。

相关推荐
Gse0a362g3 分钟前
Go - Zerolog使用入门
开发语言·后端·golang
KhalilRuan3 分钟前
Burst编译器的底层原理
java·开发语言
huwuhang6 分钟前
跨平台电子书阅读器 | Readest最新版 安卓版+PC版全平台
android·前端·javascript
C澒7 分钟前
AI 生码:RAG 检索优化实现可评估、可回溯工程化
前端·ai编程
Shirley~~7 分钟前
力扣hot100:每日温度
开发语言·javascript·ecmascript
条tiao条8 分钟前
不止语法糖:TypeScript Set 与 Map 深度解析
前端·javascript·typescript
froginwe1128 分钟前
《WebPages 邮局》
开发语言
freewlt29 分钟前
React Server Components 深度解析:从原理到实战的完整指南
前端·javascript·react.js
@insist12338 分钟前
网络工程师-广域网与接入网技术(一):核心协议与流量控制
开发语言·网络·网络工程师·软考·软件水平考试
zhensherlock1 小时前
Protocol Launcher 系列:1Writer iOS 上的 Markdown 文档管理
javascript·笔记·ios·typescript·node.js·iphone·ipad