JS进阶 - 实现call、apply、bind

96 阅读3分钟

实现 call 方法

功能

  1. call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
  2. 传入的this如果是nullundefined时,会自动替换为指向全局对象,原始值会被转换了对应的包装对象

实现

Function.prototype.myCall = function (thisArg, ...args) {
  // 因为调用时是隐式绑定,所以此时this是被调用的函数
  // 保存被调用的函数
  var fn = this;

  // 根据规则,传入null或undefined时,浏览器环境会替换为window
  thisArg =
    thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;

  // 将调用函数作为传入thisArg的属性
  thisArg.fn = fn;

  // 利用 隐式绑定规则,绑定调用函数中的this为传入的thisArg
  var result = thisArg.fn(...args);

  delete thisArg.fn;

  return result;
};

function foo() {
  console.log(this);
}

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

var obj = {
  name: "zhangsan",
  age: 28,
};

foo.call(null); // window
foo.call(undefined); // window
foo.call(obj); // obj
foo.call(100); // Number{100}

foo.myCall(null); // window
foo.myCall(undefined); // window
foo.myCall(obj); // obj
foo.myCall(100); // Number{100}

var result1 = sum.call(obj, 10, 20); 
console.log(result1); // 30

var result2 = sum.myCall(obj, 10, 20);
console.log(result2); // 30

实现 apply 方法

功能

  1. apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数
  2. 传入的this如果是nullundefined时,会自动替换为指向全局对象,原始值会被转换了对应的包装对象

实现

Function.prototype.myApply = function (thisArg, args) {
  // 因为调用时是隐式绑定,所以此时this是被调用的函数
  // 保存被调用的函数
  var fn = this;

  // 根据规则,传入null或undefined时,浏览器环境会替换为window
  thisArg =
    thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;

  // 将调用函数作为传入thisArg的属性
  thisArg.fn = fn;

  args = args || [];

  // 利用 隐式绑定规则,绑定调用函数中的this为传入的thisArg
  var result = thisArg.fn(...args);

  delete thisArg.fn;

  return result;
};

function foo() {
  console.log(this);
}

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

var obj = {
  name: "zhangsan",
  age: 28,
};

foo.apply(null); // window
foo.apply(undefined); // window
foo.apply(obj); // obj
foo.apply(100); // Number{100}

foo.myApply(null); // window
foo.myApply(undefined); // window
foo.myApply(obj); // obj
foo.myApply(100); // Number{100}

var result1 = sum.apply(obj, [10, 20]);
console.log(result1); // 30

var result2 = sum.myApply(obj, [10, 20]);
console.log(result2); // 30

实现 bind 方法

功能

  1. bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

实现

Function.prototype.myBind = function (thisArg, ...args1) {
  // 因为调用时是隐式绑定,所以此时this是被调用的函数
  // 保存被调用的函数
  var fn = this;

  // 根据规则,传入null或undefined时,浏览器环境会替换为window
  thisArg =
    thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;

  function bindedFn(...args2) {
    thisArg.fn = fn;

    // 收集调用bind()时传入的参数,以及调用bind后返回函数的参数
    var args = [...args1, ...args2];
    var result = thisArg.fn(...args);

    delete thisArg.fn;

    return result;
  }

  return bindedFn;
};

function foo(...args) {
  console.log(this, ...args);
}

var obj = {
  name: "zhangasan",
  age: 28,
};

var foo1 = foo.myBind(null);
foo1(10); // window 10

var foo2 = foo.myBind(obj, 10);
foo2(20); // obj 10 20

  • 如果认为本篇知识点梳理的尚可,欢迎点赞
  • 如果有需要补充、指正的地方,也欢迎评论留言哦~