手寫bind函數


實現bind函數

參考MDN提供的Polyfill方案

Function.prototype.myBind = function(context){
  //這里對調用者做一個判斷,如果不是函數類型,直接拋異常
  if(typeof this !== 'function'){
    throw '調用必須為函數'
  }
  //當我們調用bind函數時,我們可能傳了不只一個參數
  //如 fun.bind({}, arg1, arg2)
  //我們需要把后面的參數拿出來
  let args = Array.prototype.slice.call(arguments, 1);
  let fToBind = this; 
  let fNOP = function(){};
  let fBound = function(){
    return fToBind.apply(this instanceof fNOP ? this : context, args.concat(arguments));
  }
  if(this.prototype){
    fNOP.prototype = this.prototype;
  }

  fBound.prototype = new fNOP();

  return fBound;
}

 

fBound函數這里有個判斷 this instanceof FNOP 這個其實是為了避免一種情況,因為bind函數返回的是一個函數,當我們把這個函數實例化(就是new fun())

根據官方文檔 當返回的函數被實例化的時候,this指向會鎖定指向該實例,不管我們傳入的參數指定this指向。

在下面我們 返回的fBound函數時 繼承一個空函數 FNOP, 當返回的函數被實例化之后,this instanceof fNOP 結果為true,從而指定this指向

function a (){}
function b (){}

a.prototype = new b();

//如果我們返回的函數實例化了  
let c = new a();
c instanceof b //true
//但是大多數情況我們都是
a instanceof b // false

如果這里明白了,那后面的就簡單了,context 參數就是我們手動指定的this指向, 當我們綁定bind時會傳遞多個參數,執行的時候也會帶參數,我們就需要把bind

函數除掉第一個以外的參數和我們調用方式時的參數進行拼接

function foo (){}
//示例中 args 就是指的[arg1, arg2]
//args.concat(arguments) 就是將所有的arg1,arg2...arg4的參數進行拼接
let newFoo = foo.bind({}, arg1, arg2);
newFoo(arg3, arg4);

另外 arguments 參數不要搞混淆了,上面那個獲取的是bind時的參數(就是{}, arg1, arg2

下面的arguments 參數是指的調用時的 (就是 arg3, arg4)


免責聲明!

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



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