(五)实现js中的call、apply、bind函数

156 阅读1分钟

以下实现函数不会考虑过多的边界处理,只为实现功能

1.call实现

Function.prototype._call = function (thisArg, ...args) {

  const exeFn = this;

  const specialVariables = [undefined, null];

  //   考虑传参不是对象形式的边界处理
  thisArg = specialVariables.includes(thisArg) ? window : Object(thisArg);

  //   防止thisArg属性名称的命名冲突
  const key = Symbol("fn");

  thisArg[key] = exeFn;

  //   获取函数执行结果
  const result = thisArg[key](...args);

  delete thisArg[key];

  return result;

};

2.apply实现

Function.prototype._apply = function (thisArg, argArray) {

  const exeFn = this;

  const specialVariables = [undefined, null];

  //   考虑传参不是对象形式的边界处理
  thisArg = specialVariables.includes(thisArg) ? window : Object(thisArg);

  //   防止thisArg属性名称的命名冲突
  const key = Symbol("fn");

  thisArg[key] = exeFn;

  argArray = argArray || [];

  //   获取函数执行结果
  const result = thisArg[key](...argArray);

  delete thisArg[key];

  return result;

};

3.bind实现

Function.prototype._bind = function (thisArg, ...argArray) {

  return (...args) => {

    const exeFn = this;

    const specialVariables = [undefined, null];

    //   考虑传参不是对象形式的边界处理
    thisArg = specialVariables.includes(thisArg) ? window : Object(thisArg);

    //   防止thisArg属性名称的命名冲突
    const key = Symbol("fn");

    thisArg[key] = exeFn;

    //   获取函数执行结果
    const result = thisArg[key](...[...argArray, ...args]);

    delete thisArg[key];

    return result;

  };

};

4.测试代码

function foo(num1, num2, num3) {

  console.log(this.name);

  console.log(num1);

  console.log(num2);

  console.log(num3);

}

const obj = { name: "obj" };

foo._call(obj, 1, 2, 3); // obj 1 2 3

foo._apply(obj, [3, 4, 5]); // obj 3 4 5

const b = foo._bind(obj, 6, 7);

b(8); // obj 6 7 8