apply、call、bind 的区别及简易实现

#javascript

目录

1. 区别

  1. call 和 apply 的区别主要在于参数的传递方式:
    • call 接受一系列参数:fn.call(obj,arg1,arg2)
    • apply 接受一个参数数组:fn.apply(obj,[arg1,arg2])
  2. bind 与 call/apply 的主要区别 → ==是否立即执行==
    • call 和 apply 会立即执行函数
    • bind 返回一个新函数,可以稍后执行
  3. 使用场景:
    • call/apply:
      • 当你想立即调用函数,并临时改变 this 指向时使用
    • bind:
      • 当你想创建一个永久改变 this 指向新函数时使用,常用于回调函数中保持 this 指向

2. 手写 apply

// 使用ES6语法实现的apply 
Function.prototype._apply = function (context = window, args) {
  // 首先要获取那个函数调用了 apply ,即 this
  // 比如 foo.apply(bar, [1, 2, 3]) , 这里的 this 就是 foo
  context.fn = this;
  let res;
  if (Array.isArray(args)) {
    res = context.fn(...args);
  } else {
    // none args
    res = context.fn();
  }
  delete context.fn;
  return res;
};

3. 手写 call

// 使用ES6语法实现的call: 记得使用扩展运算符
Function.prototype._call = function (context = window, ...args) {
  // 首先要获取那个函数调用了 call ,即 this
  // 比如 foo.call(bar, 1, 2, 3) , 这里的 this 就是 foo
  context.fn = this;

  let res = context.fn(...args);

  delete context.fn;
  return res;
};

4. 手写 bind

// 使用ES6语法实现的bind
Function.prototype._bind = function (context = window, ...args) {
  let fn = this;
  // 返回的一个新函数: 注意这里需要合并参数
  return function (...newArgs) {
    return fn.apply(context, args.concat(newArgs));
    // 如果要求不能使用 apply, 那么就使用 上面定义的 _apply
    // return fn._apply(context, args.concat(newArgs));
  };
};