call 通常比 apply 快,尤其在有 this 绑定或参数传递时;apply 在参数为数组时更简洁但需解包导致微小开销;无参时两者性能几乎无差别;现代可用扩展运算符替代 apply。

call 通常比 apply 快,尤其在有 this 绑定或参数传递的场景下。这个差异不是理论推测,而是被多个实测验证过的现象。
参数为数组时,apply 更自然但未必更快
当你手头正好是一个数组(比如 arguments 或 [1, 2, 3]),用 apply 确实更简洁:
-
sum.apply(null, [1, 2, 3])直接传入数组 - 等价写法
sum.call(null, 1, 2, 3)需要手动展开,代码冗长
但性能上,apply 在这里要多做一步:引擎需将数组解包成参数列表。这层间接操作带来微小开销,尤其在高频调用或参数量大时可测出差距。
this 指向非 null/undefined 时,call 优势明显
只要第一个参数不是 null 或 undefined,call 的执行路径更直接:
- call:直接绑定 this + 按顺序压入参数栈
- apply:先检查第二个参数是否为数组/类数组,再遍历提取每个元素,再压栈
例如:fn.call(obj, 'a', 'b') 和 fn.apply(obj, ['a', 'b']) 功能一致,但前者在 Chrome、Firefox、Edge 等主流引擎中平均快 10%–30%。
无参或仅 this 绑定时,两者几乎无差别
如果函数不需要参数,只改 this:
fn.call(obj)fn.apply(obj)
此时底层处理逻辑高度趋同,性能差异可忽略。但注意:fn.apply(obj, []) 仍略慢于 fn.call(obj),因为数组空检测和遍历逻辑依然存在。
现代替代方案值得考虑
ES6+ 提供了更清晰、性能也不输的写法:
- 用扩展运算符替代 apply:
sum(...[1, 2, 3])—— 语义清晰,V8 中性能接近 call - 箭头函数或 bind 预绑定适合复用场景,避免每次调用都重设 this
- 对高频底层库(如 each、map 实现),优先选 call;业务层可按可读性权衡
实际优化不必过度纠结单次调用,重点应放在高频循环、底层工具函数这类真正影响性能的环节。











