返回

从零手写call和apply,构建属于你的Js借用函数!

前端

Js借用函数:call、apply

函数借用 ,即改变函数的执行环境(this 指向的对象)。

我们知道函数执行时,里面的this 会指向函数所属的对象,如果想让this指向其它的对象,就可以使用call 或apply方法。

call和apply方法,都接收两个参数,第一个参数是将被修改的this指向的对象,第二个参数是函数的参数。

call方法 的第二个参数可以接收多个参数,直接写在括号内,而apply方法第二个参数是数组类型,如 func.apply(obj, [a, b, c])

函数借用的区别:

  • 语法不同,call方法的第二个参数直接放在括号内,apply方法的第二个参数是数组类型;
  • 内部实现不同,call方法是利用 func.apply(thisArg, arguments) 实现的,apply方法是利用 func.call(thisArg, ...arguments) 实现的,... 运算符可以接收任意多个参数。

借用函数实现

call

Function.prototype.call = function (context) {
  // 存储当前函数
  const fn = this;

  // 判断 `context` 是否存在,如果不存在,则置为 window 对象
  if (!context) {
    context = window;
  }

  // 在 `context` 上添加一个临时属性 `fn`,该属性的值是当前函数
  context.fn = fn;

  // 使用 `apply` 方法调用 `context.fn`,第一个参数是 `context`,第二个参数是获取除去 `context` 之外的所有参数
  const result = context.fn(...arguments);

  // 删除 `context` 上的临时属性 `fn`
  delete context.fn;

  // 返回调用结果
  return result;
};

apply

Function.prototype.apply = function (context, args) {
  // 存储当前函数
  const fn = this;

  // 判断 `context` 是否存在,如果不存在,则置为 window 对象
  if (!context) {
    context = window;
  }

  // 在 `context` 上添加一个临时属性 `fn`,该属性的值是当前函数
  context.fn = fn;

  // 使用 `call` 方法调用 `context.fn`,第一个参数是 `context`,第二个参数是 `args`
  const result = context.fn(args);

  // 删除 `context` 上的临时属性 `fn`
  delete context.fn;

  // 返回调用结果
  return result;
};