Skip to content
On This Page

JavaScript_call_apply_bind

1. 核心区别

方法调用时机参数传递返回值
call立即执行参数列表 (thisArg, arg1, arg2, ...)函数执行结果
apply立即执行参数数组 (thisArg, [arg1, arg2, ...])函数执行结果
bind返回新函数,不立即执行call(可预设参数)绑定了 this 的新函数

一句话总结call / apply临时改变 this 并立即调用;bind永久绑定 this 并返回新函数,可延迟调用。

2. 手写实现

2.1 手写 call

javascript
Function.prototype.myCall = function(context, ...args) {
    // 1. context 为 null/undefined 时指向全局对象(浏览器 window,Node global)
    context = context || globalThis;
    // 2. 用一个唯一 key 避免覆盖原对象属性
    const fnKey = Symbol();
    // 3. 将当前函数作为 context 的一个方法
    context[fnKey] = this;
    // 4. 执行函数并拿到结果
    const result = context[fnKey](...args);
    // 5. 删除临时属性
    delete context[fnKey];
    return result;
};

2.2 手写 apply(仅参数处理不同)

javascript
Function.prototype.myApply = function(context, argsArray = []) {
    context = context || globalThis;
    const fnKey = Symbol();
    context[fnKey] = this;
    const result = context[fnKey](...argsArray);
    delete context[fnKey];
    return result;
};

2.3 手写 bind(更复杂,需处理 new 和预设参数)

javascript
Function.prototype.myBind = function(context, ...boundArgs) {
    const originalFn = this;
    // 返回一个新函数
    function boundFn(...callArgs) {
        // 关键:如果通过 new 调用,this 指向实例,不应该绑定 context
        const isNewCall = this instanceof boundFn;
        const finalContext = isNewCall ? this : (context || globalThis);
        return originalFn.call(finalContext, ...boundArgs, ...callArgs);
    }
    // 维护原型链(使得 boundFn 的实例能继承原函数原型)
    if (originalFn.prototype) {
        boundFn.prototype = Object.create(originalFn.prototype);
    }
    return boundFn;
};

面试技巧:写 bind 时主动提到 new 优先级高于 bind 以及 原型链维护,能极大加分。

3. 实际使用场景

场景示例推荐方法
借用数组方法操作类数组[].slice.call(arguments)call / apply
取数组最大/最小值Math.max.apply(null, [1,2,3])apply
继承(组合继承)Parent.call(this, name)call
事件处理器中固定 thisthis.handleClick.bind(this)bind
函数科里化(预设参数)const add = (a,b)=>a+b; const add5 = add.bind(null,5);bind
防抖节流中保留 thisfn.apply(this, args)apply

技巧:结合自己项目中的一个真实案例说明,比如“用 bind 解决 React 类组件中事件回调的 this 丢失”。实际开发中,我常用 apply 处理类数组,用 bind 固定 React 事件回调的 this,用 call 实现继承。

4. 进阶考点

4.1 new 对 bind 的影响

问:“如果 bind 返回的函数被 new 调用,this 指向什么?”

答:指向新创建的实例,而不是 bind 传入的 context。因为 new 的优先级最高。

4.2 多次 bind 是否有效

javascript
function foo() { console.log(this.a); }
const obj1 = { a: 1 };
const obj2 = { a: 2 };

const bar = foo.bind(obj1).bind(obj2);
bar(); // 输出 1

解释bind 一旦绑定,其内部的 this不可再被覆盖(第二次 bind 无效)。因为第一次 bind 返回的新函数内部已经硬绑定了 obj1,再次 bind 只是包裹一层,但调用时实际执行的仍是第一次绑定的函数。