手撕Bind的两种实现方式

66 阅读1分钟

本文结合 MDN 上 Bind 的 polyfill 相关内容得出

bind 的实现方式根据【支不支持使用 new 调用新创建的构造函数】分为两种,如下:

不支持 new 调用

Function.prototype.bind1 = function(){
  var slice = Array.prototype.slice;
  var _this = this,arg = arguments[0];
  var args = slice.call(arguments,1);
  if(typeof _this !== "function"){
    throw new TypeError("trying to be bound is must be a function")
  }
  return function(){
    var funcArgs = args.concat(slice.call(arguments));
    return _this.apply(arg,funcArgs)
  }
}   

支持 new 调用

Function.prototype.bind2 = function(otherThis){
  var slice = Array.prototype.slice;
  if(typeof this !== "function"){
    throw new TypeError("trying to be bound is must be a function")
  }
  var args = slice.call(arguments,1),
      argsLen = args.length,
      _this = this,
      fNop = function(){},
      fBound = function(){
        args.length = argsLen;
        args.push.apply(args,arguments);
        return _this.apply(fNop.prototype.isPrototypeOf(this)?this:otherThis,args);
      };
   if(this.prototype){
     fNop.prototype = this.prototype;
   }
   fBound.prototype = new fNop();
   return fBound;
}

添加polyFill

如若想在自己的代码里添加 bind 的兼容,可将以上代码放入到下面的代码区块内:

if(!Function.prototype.bind){
  function(){
    ...
    // 在此处填补上面的代码即可
  }
}