手写Function.bind函数

if(!Function.prototype.bind){javascript

  Function.prototype.bind = function(oThis){php

    if(typeof this !=="function"){ //若是不函数抛出异常java

      throw new TyperError("")数组

    }app

    var aArgs = Array.prototype.slice.call(arguments,1),   //此处的aArgs是除函数外的参数函数

      fToBind = this,                  //要绑定的对象ui

      fNOP = function(){},this

      fBound = function(){spa

        return fToBind.apply(prototype

          this instanceof fNOP ? this:oThis||this,aArgs.concat(Array.prototype.slice.call(arguments)));

          )

      };

    fNOP.prototype = this.prototype;

    fBound.prototype = new fNOP();

    return  fBound;

  }

}

明白 bind 的用法就必需要知道 apply 的用法,MDN 指出,apply 是直接修改了函数内部的指向到第一个参数,并将第二个参数数组传参进函数并运行这个函数。也就是说

var obj = {test: function() { console.log(this, arguments) }}, func = obj.test; obj.test("Hello", ",", "world", "!"); func.apply(obj, ["Hello", ",", "world", "!"]); 

这两种运行方式是同样的。那么回到 Polyfill 中发现参数的写法是 args.concat(slice.call(arguments))args 是将 bind时候定义的除第一个参数外的其它参数,而此时的 arguments 是指函数调用时候的参数,经过数组的操做将这两个参数合并成一个数组传入函数内部。看个例子你可能更容易明白:

/** 代码接上 **/ var newFunc = func.bind(obj, "Hello", ","); newFunc("world", "!"); 

那么再来回答问题一,这个是典型的属性继承的方法,原本使用

bound.prototype = self.prototype 

就能够将原属性集成过来了,可是这样两个对象属性都指向同一个地方,修改 bound.prototype 将会形成 self.prototype也发生改变,这样并非咱们的本意。因此经过一个空函数 nop 作中转,能有效的防止这种状况的发生。

 

bind返回的是函数

if (!Function.prototype.bind) {
    Function.prototype.bind = function(obj) {
        var _self = this ,args = arguments; return function() { _self.apply(obj, Array.prototype.slice.call(args, 1)); } } }
相关文章
相关标签/搜索