Skip to content

手写 bind、apply、call

手写 call

  • call() :在使⽤⼀个指定的 this 值和若⼲个指定的参数值的前提下调⽤某个函数或⽅法。

思路

  1. 将函数设为对象的属性;
  2. 执⾏该函数;
  3. 删除该函数
javascript
Function.prototype.myCall = function (context, ...args) {
  // 判断是否是undefined和null
  if (typeof context === "undefined" || context === null) {
    context = window;
  }
  let fnSymbol = Symbol();
  context[fnSymbol] = this;
  let fn = context[fnSymbol](...args);
  delete context[fnSymbol];
  return fn;
};

手写 apply

  • apply 的实现跟 call 类似,只是⼊参不⼀样,apply 为数组
javascript
Function.prototype.myApply = function (context, args) {
  // 判断是否是undefined和null
  if (typeof context === "undefined" || context === null) {
    context = window;
  }
  let fnSymbol = Symbol();
  context[fnSymbol] = this;
  let fn = context[fnSymbol](...args);
  delete context[fnSymbol];
  return fn;
};

手写 bind

  • bind() ⽅法会创建⼀个新函数。
  • 当这个新函数被调⽤时,bind() 的第⼀个参数将作为它运⾏时的 this,
  • 之后的⼀序列参数将会在传递的实参前传⼊作为它的参数

bind 函数的特点:

  1. 返回⼀个函数;
  2. 可以传⼊参数;
  3. ⼀个绑定函数也能使⽤ new 操作符创建对象;当 bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,但传⼊的参数依然⽣效。
javascript
Function.prototype.myBind = function (context) {
  if (typeof this !== "function") {
    throw new Error(
      "Function.prototype.bind - what is trying to be bound is not callable"
    );
  }
  var self = this;
  var args = Array.prototype.slice.call(arguments, 1);
  var fNOP = function () {};
  var fBound = function () {
    var bindArgs = Array.prototype.slice.call(arguments);

    // 当作为构造函数时,this 指向实例,此时结果为 true,将绑定函数的 this 指向该实例,可以让实例获得来⾃绑定函数的值
    // 当作为普通函数时,this 指向 window,此时结果为 false,将绑定函数的 this 指向 context

    return self.apply(
      this instanceof fNOP ? this : context,
      args.concat(bindArgs)
    );
  };
  fNOP.prototype = this.prototype;
  fBound.prototype = new fNOP();
  return fBound;
};

极简版本

javascript
Function.prototype.myBind = function (context) {
  // 判断是否是undefined 和 null
  if (typeof context === "undefined" || context === null) {
    context = window;
  }
  self = this;
  return function (...args) {
    return self.apply(context, args);
  };
};

Released under the MIT License.