call的核心目标是复用函数逻辑并精准控制this指向,适用于类数组转换、构造函数继承、工具函数上下文切换及异步回调中this修复。

显式绑定 call 在方法借用场景下,核心目标是复用已有函数逻辑,同时精准控制 this 指向,不污染原对象、不破坏继承关系、也不引入冗余封装。
跨原型链调用数组方法
类数组对象(如 arguments、NodeList、{0: 'a', 1: 'b', length: 2})没有 Array.prototype 上的方法,但可以直接借用:
- 用 Array.prototype.slice.call(arrayLike) 转为真数组,不修改原对象原型
- 用 Array.prototype.push.call(obj, item) 向类数组添加元素,只需满足 有 length 属性 + 数字索引
- 避免写
obj.__proto__ = Array.prototype—— 会污染原型链,且不可靠
构造函数间属性继承
子类实例要获得父类通过 this 初始化的属性(如 name、age),必须在子构造函数中显式调用:
- Parent.call(this, ...args) 是标准做法,把父类内部的 this.xxx = xxx 行为应用到当前子实例上
- 必须放在子构造函数第一行,确保实例属性尽早挂载
- 参数需完整传递(如
Animal.call(this, name, age)),否则父类初始化逻辑失效
工具函数适配不同上下文
当一个函数需要灵活作用于多个对象时,call 提供轻量、即时的上下文切换:
- 例如遍历类数组:[].forEach.call(nodelist, handler, thisArg) —— 第三个参数指定 handler 内部的 this
- 比 bind 更节省内存:不需要预创建新函数,适合一次性调用
- 比箭头函数更可控:箭头函数无法重绑 this,而 call 可在每次调用时动态指定
事件或回调中临时修正 this
在 setTimeout、addEventListener 等异步/委托场景中,this 容易丢失,call 可用于触发时即时修复:
- 不推荐提前 bind(可能造成闭包驻留),也不依赖箭头函数(若需复用同一函数处理不同对象)
- 可写成:btn.addEventListener('click', () => handler.call(vm, event))
- 或封装一层:function invoke(fn, ctx, ...args) { return fn.call(ctx, ...args); }











