手寫call, apply, bind

call, apply, bind這三個改變this指向的函數經常被用到,無論是開發(fā)還是面試。了解其實現原理,是一名合格的前端程序員必備技能。

  • 如果還不知道call, apply, bind的基本用法,請先自行百度

動手需知

在自行實現這幾個方法前,你得知道幾個基本的知識點:

call的實現

call的關鍵兩點: 1、改變上下文指向; 2、傳入多個參數。

Function.propoType.myCall = function(content){
  // call方法只能是方法才能調用
  if(typeof this !== "function"){
   throw new TypeError("Error");
  }
  // 如果沒有指定上下文,默認是全局對象window
  // 不要寫成this.window。當this指向發(fā)生變化,可能找不到全局對象window
  content = content || window;
  let fn = Symbol(content);          // 避免屬性重復
  let args = [...arguments].slice(1)
  //改變this指向
  content[fn] = this; //給content添加一個方法 指向this
  let result = content[fn](...args);  //傳入參數
  delete content[fn];                     // 刪除fn 方法,一個中間變量用完刪除
  return result;
} 

apply 的實現

apply的關鍵兩點:1、改變上下文指向; 2、傳入參數數組。
在實現原理上基本和call差不多,主要是參數的區(qū)別。

Function.propoType.myApply = function(content){
  // apply方法只能是方法才能調用
  if(typeof this !== "function"){
   throw new TypeError("Error");
  }
  // 如果沒有指定上下文,默認是全局對象window
  // 不要寫成this.window。當this指向發(fā)生變化,可能找不到全局對象window
  content = content || window;
  let fn = Symbol(content);          // 避免屬性重復
  let args = [...arguments][1];      // 記住傳入的是數組?。?!
 //改變this指向
  content[fn] = this; //給content添加一個方法 指向this
  let result ; 
  if(args){
     result = content[fn](...args);  //傳入參數
  }else{
    result = content[fn]();  //傳入參數
  }
  delete content[fn];                     // 刪除fn 方法,一個中間變量用完刪除
  return result;
} 

bind 的實現

bind 的關鍵幾點:1、改變上下文指向;2、傳入多個參數;3、返回的是函數的方法名,不會立即執(zhí)行。

Function.propoType.myBind = function(content){
    self = this;
  // bind方法只能是方法才能調用
  if(typeof this !== "function"){
   throw new TypeError("Error");
  }
  // 可以支持柯里化傳參,保存參數
  args = [...arguments].slice(1);
  function Fn (){
 // 考慮需要綁定的函數可能是構造函數,this不會被綁定,但是參數仍然會傳遞。
      if(this instanceof Fn){
          return self(...args.concat(...arguments));//構造函數直接傳參
      }else{
          return self.apply(content,args.concat(...arguments));// apply傳的是數組
     }
  }
  return Fn;
}

執(zhí)行:

let Person = {
    name: 'Tom',
    say(x, y) {
        //console.log(this)
        console.log(`我叫${this.name}${x}${y}`)
    }
}
Person1 = {
    name: 'Tom1'
}
Person.say.myCall(Person1, ' call你干嘛', ' 哈哈哈');
Person.say.myApply(Person1, [' apply你干嘛', ' 哈哈哈',]);
Person.say.myBind(Person1, ' bind你干嘛', ' 哈哈哈kk')()

執(zhí)行結果:


結果

結果完美呈現,以上便是call, apply, bind的簡單實現。

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容