call和apply立即执行并临时切换this,bind返回新函数并永久绑定this;call按序传参,apply用数组传参,bind可预置参数且无法被call/apply覆盖已绑定this。

核心在于明确三者行为差异:call 和 apply 立即执行并临时切换 this,bind 返回新函数并永久绑定 this。切换是否“精确”,取决于你是否匹配了目标对象结构、参数形式,以及是否理解 this 的默认指向规则。
call:按顺序传参,适合已知参数个数的场景
call 接收第一个参数作为 this 指向,后续所有参数依次传入原函数。它最直观,也最容易控制参数位置。
- 当你要快速借用一个方法,并且参数数量固定时,用 call 最直接。例如:Array.prototype.push.call(arr, item1, item2) 把 item 插入类数组 arr。
- 第一个参数为 null 或 undefined 时,在非严格模式下 this 指向全局对象(浏览器中是 window),严格模式下保持 null/undefined 不变。
- 注意:如果传入原始值(如 42、'abc'),会被自动包装成对应包装对象(Number、String 实例),this 指向该包装实例。
apply:用数组传参,适合参数动态或不确定的场景
apply 和 call 功能完全一致,唯一区别是第二个参数必须是数组或类数组(如 arguments、NodeList)。它让“把一堆值当参数传进去”这件事变得自然。
- 常见用途是转发参数,比如封装 console.log:function log() { console.log.apply(console, arguments); } 这样 log(1, 'a', {}) 就等价于 console.log(1, 'a', {})。
- 也可用于求数组极值:Math.max.apply(null, [3, 7, 2]) —— 因为 Math.max 不接受数组,但 apply 能把它“展开”。
- 若传入空数组 [],相当于不传任何实参,函数接收的参数列表为空。
bind:返回绑定函数,适合需要延迟执行或复用绑定逻辑的场景
bind 不执行函数,而是返回一个新函数,其内部 this 被永久锁定为目标对象,且可预置部分参数(柯里化)。
- 事件监听器中避免 this 丢失:btn.addEventListener('click', obj.handleClick.bind(obj)),确保 handleClick 内部 this 始终是 obj。
- 支持参数预设:比如 const add5 = sum.bind(null, 5),之后调用 add5(3) 相当于 sum(5, 3)。
- bind 返回的函数无法再通过 call/apply 覆盖已绑定的 this(除非使用 new 调用,此时 this 以构造方式重置)。
切换主体前的关键检查点
无论用哪个方法,切换失败往往不是语法问题,而是上下文理解偏差:
- 确认目标对象确实拥有你需要访问的属性或方法——bind 后的函数若读取 this.name,而目标对象没定义 name,结果就是 undefined。
- 注意箭头函数没有自己的 this,它继承外层作用域的 this,因此 call/apply/bind 对箭头函数无效。
- 在 class 方法中直接传递未绑定的实例方法(如 onClick={obj.handleClick}),事件触发时 this 通常丢失,应改用 bind、箭头函数或 public class field 语法。










