返回

JavaScript | 温故知新:手把手教你手写 call、apply、bind

前端

call、apply 和 bind 是 JavaScript 中用于改变函数执行上下文(即 this 所指向的对象)的内置方法。这三个方法允许我们以不同的对象作为函数的执行上下文来调用函数。这在 JavaScript 中非常有用,因为函数的执行上下文对函数的行为有很大的影响。

区别

  • call() 方法接受一个参数列表,并将它们作为函数的参数传递。
  • apply() 方法也接受一个参数列表,但它是以数组的形式传递的。
  • bind() 方法不立即调用函数,而是返回一个新的函数,该函数在调用时将使用指定的 this 值。

手写实现

call

Function.prototype.myCall = function(context) {
  // 获取调用函数的参数
  const args = [...arguments].slice(1);

  // 将函数绑定到指定的对象
  context.fn = this;

  // 调用函数并返回结果
  const result = context.fn(...args);

  // 删除绑定的函数
  delete context.fn;

  return result;
};

apply

Function.prototype.myApply = function(context, args) {
  // 将函数绑定到指定的对象
  context.fn = this;

  // 调用函数并返回结果
  const result = context.fn(...args);

  // 删除绑定的函数
  delete context.fn;

  return result;
};

bind

Function.prototype.myBind = function(context) {
  // 获取调用函数的参数
  const args = [...arguments].slice(1);

  // 返回一个新的函数
  return (...bindArgs) => {
    // 将函数绑定到指定的对象
    context.fn = this;

    // 调用函数并返回结果
    const result = context.fn(...args, ...bindArgs);

    // 删除绑定的函数
    delete context.fn;

    return result;
  };
};

用法示例

// 使用 call() 方法
const person = {
  name: 'John Doe',
  greet: function() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

const anotherPerson = {
  name: 'Jane Doe'
};

person.greet.myCall(anotherPerson); // 输出: Hello, my name is Jane Doe

// 使用 apply() 方法
const numbers = [1, 2, 3, 4, 5];

const max = Math.max.apply(Math, numbers); // 输出: 5

// 使用 bind() 方法
const button = document.querySelector('button');

button.addEventListener('click', person.greet.myBind(anotherPerson)); // 当按钮被点击时,输出: Hello, my name is Jane Doe

总结

call、apply 和 bind 是 JavaScript 中非常有用的方法,它们允许我们以不同的对象作为函数的执行上下文来调用函数。这在 JavaScript 中非常有用,因为函数的执行上下文对函数的行为有很大的影响。