手寫Function.bind函數


if(!Function.prototype.bind){

  Function.prototype.bind = function(oThis){

    if(typeof this !=="function"){ //如果不函數拋出異常

      throw new TyperError("")

    }

    var aArgs = Array.prototype.slice.call(arguments,1),   //此處的aArgs是除函數外的參數

      fToBind = this,                  //要綁定的對象

      fNOP = function(){},

      fBound = function(){

        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;

  }

}

明白 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)); } } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM