用原生js實現一個bind方法

bind用法介紹:

bind()方法建立一個新的函數, 當被調用時,將其this關鍵字設置爲提供的值,在調用新函數時,在任何提供以前提供一個給定的參數序列。

這段是來自MDN:bind的介紹,咱們能夠理解bind方法返回一個新的函數,這個函數內部的this指向提供的參數值,來看個例子react

const person = {
      age: 20,
      getAge() {
        return this.age
      }
    }
  const getAge = person.getAge
  console.log(getAge()) // output :undefined

上面代碼輸出了undefined,什麼緣由呢?相信你們都知道,getAge()執行時內部的this指向了window,而window並無age這個屬性,咱們並無定義全局的age變量,那咱們怎麼解決這個問題呢?那就是用哪一個bind方法,須要注意的是bind方法的兼容性,IE9以上包括IE9。其餘現代瀏覽器不用說確定是支持的。下面咱們用一下bind方法來修改上面的例子面試

const person = {
      age: 20,
      getAge() {
        return this.age
      }
    }
  const getAge = person.getAge.bind(person)
  console.log(getAge()) // output :20

咱們看到經過bind方法就能夠輸出age了數組

bind語法格式

fun.bind(thisArg[, arg1[, arg2[, ...]]])

參數

thisArg瀏覽器

當綁定函數被調用時,該參數會做爲原函數運行時的 this 指向。當使用new 操做符調用綁定函數時,該參數無效。

arg1, arg2, ...app

當綁定函數被調用時,這些參數將置於實參以前傳遞給被綁定的方法

返回值

返回由指定的this值和初始化參數改造的原函數拷貝

我的理解:bind方法接受的第一個參數是你想綁定的this值,一般是個對象,這個對象在函數內部用this能夠獲取到,第一個參數後面能夠跟若干個參數,這些參數能夠在bind的時候傳遞,至關於預設參數。函數

好了,知道用法和參數後咱們就能夠實現一個簡陋版的了oop

Function.prototype.bind=function (context) {
  if(typeof this !=='function'){
    throw new Error(`${this.name} is not a function`)
  }
  const srcFun=this// 保存原始函數
  const arg=Array.prototype.slice.call(arguments,1)// 把arguments類數組轉爲真實數組
  let noop=function(){}
  const fBound= function () {
   if(this instanceof noop){
     context=this
   }
    // 合併新舊參數
    return srcFun.apply(context,arg.concat(Array.prototype.slice.call(arguments,0)))
  }
  if(this.prototype){
    noop.prototype=this.prototype//維護原型關係,指向原始函數
  }
  fBound.prototype=new noop()//新函數的prototype的__proto__指向noop.prototype
  return fBound
}

很簡陋,沒有嚴謹的判斷。學習

一個綁定函數也能使用new操做符建立對象:這種行爲就像把原函數當成構造器。提供的 this 值被忽略,同時調用時的參數被提供給模擬函數。

上面是MDN的一段話,也就是bind返回的函數也能夠當作構造函數來用,此時bind傳遞的第一個參數無效,可是其餘參數有效。this

那麼要作判斷處理就是prototype

//代碼2
if(this instanceof noop){
     context=this
   }

這段代碼就能夠區分出是在把函數當作構造函數來new了仍是當作普通方法來調用了,咱們知道
當new 的時候實際作了這點事

var obj={}
obj._proto_=構造函數的prototype
構造函數.call(obj)

因此如今在代碼2中的this是構造函數的實例,那就得更改bind後的函數,讓bind後的fBound函數的prototype指向noop的實例,這樣此時的this就藉助noop實例指向了noop的原型,那麼this instanceof noop就是true了

總結

上面是我對bind方法的一些理解和實現,僅供參考和學習。bind方法在react中會比較經常使用到,有些面試題也會讓本身實現一個,因此嘗試一下也能學到很多東西了。

相關文章
相關標籤/搜索