返回

探究apply、call、bind的原理与ES6手写实现

前端

一、apply、call、bind简介

在JavaScript中,Function.prototype包含三个方法:apply()、call()和bind()。这三个方法都允许您以不同的方式调用函数,从而实现函数的复用和灵活性。

  • apply()方法 :apply()方法接收两个参数:第一个参数是要调用的函数,第二个参数是要作为函数参数传递的数组。apply()方法会将数组中的元素作为函数的参数,并执行函数。
  • call()方法 :call()方法接收两个参数:第一个参数是要调用的函数,第二个参数是要作为函数的this值传递的值。call()方法会将第二个参数作为函数的this值,并执行函数。
  • bind()方法 :bind()方法接收两个参数:第一个参数是要调用的函数,第二个参数是要作为函数的this值传递的值。bind()方法会返回一个新的函数,该函数的this值被绑定为第二个参数。

二、apply、call、bind原理

这三个方法的原理都很简单,都是通过修改函数的this值来实现的。

  • apply()方法 :apply()方法会将数组中的元素作为函数的参数,并将函数的this值设置为数组的第一个元素。
  • call()方法 :call()方法会将第二个参数作为函数的this值,并将函数的参数作为函数的参数。
  • bind()方法 :bind()方法会返回一个新的函数,该函数的this值被绑定为第二个参数。当调用该函数时,函数的this值将被设置为第二个参数,而函数的参数则与原函数的参数相同。

三、apply、call、bind区别

这三个方法的区别主要在于参数的传递方式和this值的设置方式。

  • apply()方法 :apply()方法的参数是一个数组,数组中的元素作为函数的参数。函数的this值设置为数组的第一个元素。
  • call()方法 :call()方法的参数是一个一个传递的,函数的this值设置为第一个参数。函数的参数从第二个参数开始传递。
  • bind()方法 :bind()方法不接收任何参数,它返回一个新的函数,该函数的this值被绑定为第一个参数。当调用该函数时,函数的参数与原函数的参数相同。

四、ES6手写实现

在ES6中,这三个方法都可以通过以下方式手写实现:

Function.prototype.myApply = function (context, arr) {
  context.fn = this;
  let result = context.fn(...arr);
  delete context.fn;
  return result;
};

Function.prototype.myCall = function (context, ...args) {
  context.fn = this;
  let result = context.fn(...args);
  delete context.fn;
  return result;
};

Function.prototype.myBind = function (context, ...args) {
  let fn = this;
  return function (...args2) {
    return fn.apply(context, [...args, ...args2]);
  };
};

五、总结

apply()、call()和bind()都是非常有用的方法,可以帮助您更好地控制函数的调用方式和this值。这三个方法在实际开发中经常被使用,掌握它们的原理和用法可以帮助您写出更灵活和可复用的代码。