手写bind

71 阅读1分钟

bind的特点:

  • 位于Function.prototype上
  • fn.bind(asThis)
  • fn.bind(asThis, param1, param2)
  • fn.bind(asThis)()
  • fn.bind(asThis, param1, param2)()
  • fn.bind(asThis)(params1)
  • fn.bind(asTHis, param1, param2)(param3, param4)
  • 支持new操作符

不支持new的bind

 function bind(asThis, ...args) {
   const fn = this
   return function(...args2) {
     return fn.call(asThis, ...args, ...args2)
   }
 }

// ES3写法
var slice = Array.prototype.slice
function bind(asThis) {
   // this 就是函数
   var fn = this
   var args = slice.call(arguments, 1)
   return function() {
     var args1 = slice.call(arguments, 0)
     return fn.apply(asThis, args.concat(args1))
    }
 }

支持new的bind

new一个函数究竟做了什么事情

  1. 创建临时对象temp
  2. 函数内部this指向临时对象
  3. 绑定原型 temp.__proto__ = 构造函数.prototype
  4. 执行函数,返回临时对象
function _bind(asThis, ...args) {
  // this 就是函数
  var fn = this;
  function resultFn(...args2) {
    // 虽然构造函数明确返回undefined,但是会被忽略掉,然后返回临时创建的对象
    return fn.call(this instanceof resultFn ? this : asThis, ...args, ...args2);
  }
  resultFn.prototype = fn.prototype;
  return resultFn;
}

// ES3写法
var slice = Array.prototype.slice;
function bind(asThis) {
  // this 就是函数
  var args = slice.call(arguments, 1);
  var fn = this;
  if (typeof fn !== "function") {
    throw new Error("bind 必须调用在函数身上");
  }
  function resultFn() {
    var args2 = slice.call(arguments, 0);
    return fn.apply(
      resultFn.prototype.isPrototypeOf(this) ? this : asThis,
      args.concat(args2)
    );
  }
  resultFn.prototype = fn.prototype;
  return resultFn;
}