手寫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)); } } }
相關文章
相關標籤/搜索