JavaScript之bind函数的模拟实现

110 阅读1分钟

一、bind函数的作用

1、改变this指向

2、返回一个新的函数,但不执行,需要调用才会执行

二、带参数的bind模拟实现

var foo = { value: 1 }; 

function bar(name, age) { 

 console.log(this.value); 

 console.log(name); 

 console.log(age); 

 };

var bindFoo = bar.bind(foo, 'daisy');

bindFoo('18');  

// 输出结果

// 1 

// daisy 

// 18

改变this指向,可以用之前的文章里定义的apply或者call实现,这里为了方便,用原生的apply实现,注意这边的传参很有意思,在bind的时候传入了一个,在执行的时候又传入了一个,需要在模拟的bind函数中对参数进行合并

模拟函数如下:

Function.prototype.bind2 = function (context) { 

 var self = this; 

 var args = Array.prototype.slice.call(arguments, 1); 

 return function(){ 

 var bindArgs = Array.prototype.slice.call(arguments); 

 self.apply(context, args.concat(bindArgs)); 

 } 

};

三、构造函数中的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) {
      // 当执行Function.prototype.bind()时, this为Function.prototype 
      // this.prototype(即Function.prototype.prototype)为undefined
      fNOP.prototype = this.prototype; 
    }
    // 下行的代码使fBound.prototype是fNOP的实例,因此
    // 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例
    fBound.prototype = new fNOP();

    return fBound;
  };
}