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 用得最少。但面试爱问区别,所以三个都得懂。

相关推荐
Chester_19995 小时前
CSP202203C.计算资源调度器
开发语言·数据结构·c++·蓝桥杯
FreeTinker5 小时前
HTML本地存储技术解析:localStorage与sessionStorage的原理、差异与应用场景
前端·html
qq_452396235 小时前
第十二篇:《全链路监控与可观测性:前端错误追踪与性能分析》
前端
海兰6 小时前
【应用】基于 Next.js 16 + Python mplfinance的金融K线图与技术指标可视化平台(三)
javascript·python·金融
EXI-小洲6 小时前
Java 操作 Word:字符串替换、图片插入、动态生成表格与API接口下载
java·开发语言·spring boot·word
wangruofeng6 小时前
Phosphor Icons 官网源码拆解:URL 即存储、水波动画与 7362 Star 图标库的架构实践
前端·架构·github
BigTopOne6 小时前
WebRTC Native / Android 开发学习资源整理
前端
会周易的程序员6 小时前
给 PLC 写一个字节码虚拟机:STVM 虚拟机架构设计
开发语言·c++·虚拟机·软plc·iec61131·stvm
机器视觉知识推荐、就业指导6 小时前
为什么老说“纯 Qt 没啥就业市场”?
开发语言·qt
telepan6 小时前
Qt 开发避坑与性能指南:如何优雅、安全地定义全局常量字符串?
开发语言·qt