返回

手写call、apply、bind的实现思路及面试题分析

前端

手写call、apply、bind思路及实现

一、call、apply、bind的简介及区别

首先介绍下call、apply、bind函数的含义和它们的区别:

  1. call()apply()方法都可立即执行一个函数,其中call()传递的参数以逗号分隔,apply()传递的参数存储在数组中。
  2. bind()方法和 call()apply()方法类似,但是它并不立即执行函数,而是返回一个新函数,这个新函数的 this 值被设置为绑定函数的第一个参数,之后的参数将作为新函数的参数。

二、手写call、apply、bind实现

1. 手写call的实现思路

Function.prototype.myCall = function(context) {
  if (typeof this !== "function") {
    throw new TypeError("Error: This is not a function");
  }
  context = context || window;
  context.fn = this;
  const args = [];
  for (let i = 1; i < arguments.length; i++) {
    args.push(arguments[i]);
  }
  const result = context.fn(...args);
  delete context.fn;
  return result;
};

2. 手写apply的实现思路

Function.prototype.myApply = function(context, arr) {
  if (typeof this !== "function") {
    throw new TypeError("Error: This is not a function");
  }
  context = context || window;
  context.fn = this;
  const result = context.fn(...arr);
  delete context.fn;
  return result;
};

3. 手写bind的实现思路

Function.prototype.myBind = function(context) {
  if (typeof this !== "function") {
    throw new TypeError("Error: This is not a function");
  }
  const fn = this;
  const args = [];
  for (let i = 1; i < arguments.length; i++) {
    args.push(arguments[i]);
  }
  return function() {
    fn.apply(context, args.concat(...arguments));
  };
};

三、面试题分析

1. 手写call的实现及原理

考察点:

  • 对函数的理解。
  • 对函数的作用域和上下文对象的理解。

2. 手写apply的实现及原理

考察点:

  • 对函数的理解。
  • 对函数的作用域和上下文对象的理解。
  • 对数组的理解。

3. 手写bind的实现及原理

考察点:

  • 对函数的理解。
  • 对函数的作用域和上下文对象的理解。
  • 对闭包的理解。

4. call、apply、bind的区别

考察点:

  • 对call、apply、bind这三个方法的理解。
  • 对这三个方法的异同点的理解。