关于bind(..) polyfill 代码的理解

关于bind(..) polyfill 代码的理解

你不知道的JavaScript(上卷)p93

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <script>
    /*
      尽管代码部分仍未看懂,但应该还是有一点理解了
    */
    // 判断是否有bind方法,没有就执行添加
    // 如果想在浏览器运行这个方法,可以将这个判断!Function.prototype.bind直接改成true
    if (!Function.prototype.bind) { 
      Function.prototype.bind = function(oThis) { // oThis在本例中就是obj
        // 做的事:判断调用bind方法的对象是不是一个函数function,若不是则报错
        // 也就是说此方法只能是函数调用吗?这部分没太理解为什么要这样做
        if (typeof this !== "function") { 
          // 与 ECMAScript 5 最接近的 
          // 内部 IsCallable 函数 
          throw new TypeError( "Function.prototype.bind - what is trying " + "to be bound is not callable" ); 
        } 
        // Array.prototype.slice.call将类数组转换为数组,同时剔除了传入的第一个参数,即对象,而如果除了对象,还传入了其他参数,则参数会保留
        // 把除了第一个参数(第一个参数用于绑定 this) 之外的其他参数都传给下层的函数(这种技术称为“部分应用”, 是“柯里化” 的一种)
        var aArgs = Array.prototype.slice.call( arguments, 1 ), 
        fToBind = this, // 本例中this就是foo
        fNOP = function(){}, 
        fBound = function(){ 
          return fToBind.apply(
            // 如果this的原型链上有fNOP并且oThis转换为布尔值是true才用本来指向的this,否则将它转成oThis
            // 这里就是判断是否要修改绑定的对象了
            // 这里我的理解是如果this instanceof fNOP并且oThis不是undefined或null等,就认为开发者是特意这样设置的,按照开发者的意愿绑定对象,即使用oThis
            // 但是this instanceof fNOP 这句又是什么意思呢
            // this 的原型链上有fNOP的原型才会是true,什么情况下它会是true呢?
            // 我认为这里是为了保持绑定的优先级(p94页)
            // 优先级: new > 显示绑定 > 隐式绑定 > 默认绑定
            // 原文说:这段代码会判断硬绑定函数是否是被 new 调用, 如果是的话就会使用新创建的 this 替换硬绑定的 this。
            // 回忆一下,fBound的原型是fNOP构造的对象,那么当fBound作为构造函数,也就是说new调用时this指向的就是fNOP构造的对象,此时this 的原型链上有fNOP的原型,此时会返回true
            // 这里需要补充一点:如果传入的是null/undefined,oThis就是null/undefined,但是由于如果你把 null 或者 undefined 作为 this 的绑定对象传入 call、 apply 或者 bind, 这些值在调用时会被忽略, 实际应用的是默认绑定规则(原文p96)
            // 也就是说如果传入null/undefined等值,最后还是会用默认绑定。
            // 否则显式调用都会生效

            (this instanceof fNOP && oThis ? this : oThis ), 
            // 将之前的参数和新传入的参数拼接起来
            aArgs.concat( Array.prototype.slice.call( arguments ) )
          ); 
        }; 
        fNOP.prototype = this.prototype; 
        fBound.prototype = new fNOP(); 
        return fBound; 
      }; 
    };
    function foo(num){
      this.a = num;
    }
    var obj={};
    var tmp =foo.bind(obj);
    tmp(2);
    console.log(obj.a); // 2
    var tmp2 = new tmp(3);
    console.log(tmp2.a); //3
  </script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值