call、apply 和 bind
JavaScript 中 `call`、`apply` 和 `bind` 的共同点与差异,以及它们和 this 绑定的关系。
#frontend
#javascript
#synthesis
#growing
[!info] related notes
- 所属 MOC: ECMAScript MOC
- 相关概念: this 关键字, 箭头函数
call、apply 和 bind
这三个方法都和函数调用时的 this 指向有关。
一句话定义
call:立即调用函数,参数逐个传apply:立即调用函数,参数以类数组对象(包括数组)传bind:不立即调用,返回一个绑定好this的新函数
最小例子
fn.call(obj, 1, 2)
fn.apply(obj, [1, 2])
const newFn = fn.bind(obj, 1, 2)
共同点
它们可为普通函数指定 this;箭头函数使用词法 this,已绑定函数也不能靠再次 call/apply/bind 改绑。参数传递和部分应用仍然有效。
差异
call
- 立即执行
- 适合已知参数列表的场景
apply
- 立即执行
- 适合参数已经在数组里的场景
bind
- 不会立刻执行
- 更像提前生成一个“this 已固定”的新函数
- 适合事件回调、延迟执行与左侧参数预填;参数预填不等同于完整柯里化
最容易误解的点
-
bind返回的是新函数,不是执行结果 -
箭头函数没有自己的
this,所以对箭头函数使用这三者时,经常看不到预期效果 -
apply 接收类数组参数列表,不等同于可迭代协议;Set 应先转数组或使用展开调用。
-
用 new 调用可构造的绑定函数时,会忽略绑定的 this,但保留预填参数;不可构造的目标不会因 bind 变得可构造。
最短记忆方式
call/apply 立刻调,bind 先绑后用。
学习检查
不看正文回答:
call、apply、bind的共同点是什么?- 哪两个会立即执行函数,哪个会返回新函数?
call与apply的参数传递形式有什么区别?- 为什么
bind常用于事件回调或延迟执行? - 为什么对箭头函数调用这三个 API 时,通常不能像普通函数那样改变它的
this? - 给一个“方法丢失 this”的例子,分别说明用
call和bind修复时行为如何不同。