call、apply、bind均基于“函数作为对象属性调用时this指向该对象”的机制;call立即执行并逐个传参,apply立即执行但参数以数组形式传入,bind返回绑定this和预置参数的新函数,支持延迟调用与new调用。

call 的底层实现逻辑
call 的核心是“临时把函数挂到目标对象上,执行完立刻删掉”。它接收两个部分:第一个参数是新的 this 值,后面所有参数是原函数要接收的实际参数。
实现关键点:
- 若未传 context,默认指向全局对象(如浏览器中为 window)
- 用一个临时属性(比如 fn 或 Symbol)把当前函数赋给 context 对象
- 用展开语法或 Array.from(arguments).slice(1) 提取其余参数并传入执行
- 执行后立即删除该临时属性,避免污染 context
- 返回函数执行结果
apply 的底层实现逻辑
apply 和 call 几乎完全一致,唯一区别是参数接收方式:apply 的第二个参数必须是数组(或类数组),而 call 是逐个列出。
实现时只需把参数处理逻辑换成:
- 判断 arguments[1] 是否存在且为数组/类数组
- 直接将该数组作为参数传入 context.fn(...args) 或用 apply 自身调用(但手写时不建议递归)
- 其余流程(绑定、执行、清理)与 call 完全相同
bind 的底层实现逻辑
bind 不执行函数,而是返回一个新函数。这个新函数在被调用时,this 固定为 bind 时传入的第一个参数,同时支持参数预设(柯里化)和 new 调用兼容。
实现要点:
- 保存原始函数引用和预设参数(Array.from(arguments).slice(1))
- 返回的函数内部需判断是否通过 new 调用(this instanceof bound)
- 如果是 new 调用,忽略 bind 绑定的 this,让实例继承原函数原型
- 否则用 apply 将预设参数与调用时参数合并后执行
- 手动设置返回函数的 prototype,保证继承链不被破坏
三者共通的本质
它们都依赖 JavaScript 中“函数作为对象属性被调用时,this 指向该对象”这一机制。没有魔法,只是借用了对象属性调用的天然规则。
区别只在于:
- call:立即执行,参数逐个传
- apply:立即执行,参数以数组形式传
- bind:不执行,返回绑定后的新函数,支持延迟调用和构造调用











