02-手写实现call、apply、bind

108 阅读1分钟

通过js模拟实现,不过度考虑边界情况

call的实现

Function.prototype.myCall = function (thisArg, ...argArray) {
  // 1.thisArg转换对象类型和默认值处理
  thisArg =
    thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
  // 2.拿到执行函数添加到this对象上
  thisArg.fn = this;
  // 3.执行函数(this通过隐式绑定)
  var res = thisArg.fn(...argArray);
  // 删除添加的属性
  delete thisArg.fn;
  // 4.返回结果
  return res;
};

function sum(num1, num2) {
  console.log(this, num1, num2);
  return num1 + num2;
}

var res = sum.call('call', 1, 2); // [String: 'call'] 1 2

var res1 = sum.myCall('myCall', 1, 2); // [String: 'myCall'] { fn: [Function: sum] } 1 2

apply的实现

apply和call主要在参数区别

Function.prototype.myApply = function (thisArg, argArray) {
  // 1.thisArg转换对象类型和默认值处理
  thisArg =
    thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
  // 2.拿到执行函数添加到this对象上
  thisArg.fn = this;
  // 3.执行函数(this通过隐式绑定)
  if (Array.isArray(argArray)) {
    var res = thisArg.fn(...argArray);
  } else {
    var res = thisArg.fn();
  }
  // 删除添加的属性
  delete thisArg.fn;
  // 4.返回结果
  return res;
};

function sum(num1, num2) {
  console.log(this, num1, num2);
  return num1 + num2;
}

var res = sum.apply('apply', [1, 2]); // [String: 'apply'] 1 2

var res1 = sum.myApply('myApply', [1, 2]); // [String: 'myApply'] { fn: [Function: sum] } 1 2

bind的实现

Function.prototype.myBind = function (thisArg, ...argArray) {
  // 1.thisArg转换对象类型和默认值处理
  thisArg =
    thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
  // 2.拿到执行函数添加到this对象上
  thisArg.fn = this;
  // 3.返回绑定好this的待执行函数
  return function (...args) {
    // 4.执行函数,并拼接所有参数(this通过隐式绑定)
    var res = thisArg.fn(...argArray.concat(args));
    // 删除添加的属性
    delete thisArg.fn;
    // 5.返回结果
    return res;
  };
};

function sum(num1, num2, num3) {
  console.log(this, num1, num2, num3);
  return num1 + num2 + num3;
}

var newSum = sum.bind('bind', 1, 2);
var res = newSum(3); // [String: 'bind'] 1 2 3

var newSum1 = sum.myBind('myBind', 1, 2);
var res1 = newSum1(3); // [String: 'myBind'] { fn: [Function: sum] } 1 2 3