使用js实现bind()函数最严谨的方式

if (!Function.prototype.bind) {
  Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }

    var aArgs   = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {
          // this instanceof fBound === true时,说明返回的fBound被当做new的构造函数调用
          return fToBind.apply(this instanceof fBound
                 ? this
                 : oThis,
                 // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
                 aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    // 维护原型关系
    if (this.prototype) {
      // 这里需要判断是否存在prototype属性 应为Funtion.prototype 是不存在prototype属性的
      fNOP.prototype = this.prototype; 
    }
    // 下行的代码使fBound.prototype是fNOP的实例,因此
    // 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例
    fBound.prototype = new fNOP();

    return fBound;
  };
}

这个方法的主要几个难点 在于 第一判断是否是使用构造函数(new xx()) 还有就是原型链的关联。

这两点不容易理解 

首先 我们创建的fBound这个函数是用作最后返回的,我们传递了一个 需要绑定的oThis 进来 需要做的就是把他绑定到我们需要绑定的函数上。所以最终返回的肯定是一个 绑定好后的函数。我们先拿到调用这个函数的函数 fToBind 。

我们用this instanceof fBound 这里就是用来判断 我们返回出去的这个函数到底是 一个普通的函数 还是一个 构造函数 ,因为当我们用 new 去创建一个对象的时候 这个 函数的 this  会指向本身 比如:

function Fun(){
    console.log(this)
}

new Fun();
// Fun();

所以 this instanceof fBound === true时,说明返回的fBound被当做new的构造函数调用。如果这个时候我们还是使用传进来的oThis的话 会出现 构造函数绑定到 oThis 上 这不是我们要的结果。必须要判断。如果只想oThis 那么 你的构造函数里面的用 this声明的属性就会出问题。

还有一个 就是原型的关联问题,这里要做一个严谨的判断 因为 Function 和 Function.prototype typeof 都是 ‘function’ 类型的。但是 function.prototype 没有prototype属性。

剩下的就是正常的原型关联。这个方法相对来说是 比较严谨的。可以理解下来 之后 面试可能用的到

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值