返回

call、apply、bind 那些事儿

前端

在 JavaScript 中,函数调用时,函数内部的 this 指向函数被调用的对象。如果函数没有被任何对象调用,那么 this 指向 window 对象。

call、apply 和 bind 方法都可以改变函数的执行上下文,从而改变函数内部的 this 指向。

  • call 方法接受两个参数:第一个参数是函数要执行的上下文对象,第二个参数是函数的参数列表。
  • apply 方法与 call 方法类似,但第二个参数不是参数列表,而是一个参数数组。
  • bind 方法与 call 和 apply 方法不同,它不立即执行函数,而是返回一个新的函数,这个新函数的执行上下文被绑定到了指定的 this 值。

函数柯里化

函数柯里化是指将一个函数的参数列表分割成多个部分,并返回一个新的函数,这个新函数接受第一个参数并返回一个新的函数,这个新函数接受第二个参数,以此类推,直到所有参数都被接受。

函数柯里化可以通过 call 和 apply 方法实现。

例如,我们可以将一个计算面积的函数柯里化为一个计算周长的函数:

function area(width, height) {
  return width * height;
}

function perimeter(width, height) {
  return 2 * (width + height);
}

const perimeterCurried = perimeter.bind(null, 10);
const areaOfRectangle = perimeterCurried(5);

console.log(areaOfRectangle); // 30

函数借用

函数借用是指将一个函数的方法借用给另一个函数。

函数借用可以通过 call 和 apply 方法实现。

例如,我们可以将一个对象的 speak 方法借用给另一个对象:

const person = {
  name: 'John',
  speak: function() {
    console.log(`My name is ${this.name}`);
  }
};

const robot = {
  name: 'R2-D2'
};

person.speak.call(robot); // My name is R2-D2

函数代理

函数代理是指创建一个新的函数,这个新函数的执行上下文与另一个函数相同。

函数代理可以通过 bind 方法实现。

例如,我们可以创建一个函数代理来限制一个函数的调用次数:

function canOnlyCallOnce(func) {
  let called = false;
  return function() {
    if (!called) {
      called = true;
      func.apply(this, arguments);
    }
  };
}

const onClick = canOnlyCallOnce(function() {
  console.log('Button clicked!');
});

document.getElementById('button').addEventListener('click', onClick);

// 只会输出一次 "Button clicked!"

总结

call、apply 和 bind 是 JavaScript 中三个重要的函数调用方法。它们都可以改变函数的执行上下文,从而实现函数柯里化、函数借用和函数代理等功能。

在实际开发中,这三个方法非常有用。例如,我们可以使用函数柯里化来创建通用的函数,然后通过传递不同的参数来创建新的函数。我们可以使用函数借用来共享对象的方法,而无需复制代码。我们可以使用函数代理来限制函数的调用次数,或者创建新的函数来处理事件。