bind 源码学习

Funtion.prototype.bind 改变函数执行上下文this指向,返回一个函数

// 简单版
Function.prototype.bind = function (context) {
    var _this = this;
    var args = Array.prototype.slice.call(arguments, 1)
    return function () {
        var innerArgs = Array.prototype.slice.call(arguments)
        var finalArgs = args.concat(innerArgs)
        return _this.apply(context, finalArgs)
    }
}

在js中,有时候使用bind会有如下的情况(调用bind返回的函数时候使用new来调用,此时,bind的第一个参数无效)

function Person () {
    this.name = 'qihr'
    this.age = 18
}
var obj = {
    sex: '女'
}
var temp = Person.bind(obj)
temp(); 
console.log(obj) // {name: 'qihr', age: 18, sex: '女'}
new temp() // {name: 'qihr', age: 18}

貌似上面的方式不行了诶~~~,源码怎么实现的呢?

if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    if (typeof this !== "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 () {
          // 当通过new方法调用时,this就是fNOP的一个实例  
          return fToBind.apply(this instanceof fNOP
                                 ? this
                                 : oThis || this,
                               aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
  };
}

通过设置一个中转构造函数F,使绑定后的函数与调用bind()的函数处于同一原型链上,用new操作符调用绑定后的函数,返回的对象也能正常使用instanceof,因此这是最严谨的bind()实现。

 

posted @ 2017-09-18 22:15  RunningAndRunning  阅读(868)  评论(0编辑  收藏  举报