手寫call, apply, bind

call, apply, bind這三個改變this指向的函數常常被用到,不管是開發仍是面試。瞭解其實現原理,是一名合格的前端程序員必備技能。前端

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

動手需知

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

call的實現

call的關鍵兩點: 一、改變上下文指向; 二、傳入多個參數。面試

Function.protoType.myCall = function(content){
  // call方法只能是方法才能調用
  if(typeof this !== "function"){
   throw new TypeError("Error");
  }
  // 若是沒有指定上下文,默認是全局對象window
  // 不要寫成this.window。當this指向發生變化,可能找不到全局對象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的關鍵兩點:一、改變上下文指向; 二、傳入參數數組。 在實現原理上基本和call差很少,主要是參數的區別。數組

Function.protoType.myApply = function(content){
  // apply方法只能是方法才能調用
  if(typeof this !== "function"){
   throw new TypeError("Error");
  }
  // 若是沒有指定上下文,默認是全局對象window
  // 不要寫成this.window。當this指向發生變化,可能找不到全局對象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 的關鍵幾點:一、改變上下文指向;二、傳入多個參數;三、返回的是函數的方法名,不會當即執行。bash

Function.protoType.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;
}
複製代碼

執行:app

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')()
複製代碼

執行結果: 函數

結果
結果完美呈現,以上即是call, apply, bind的簡單實現。
相關文章
相關標籤/搜索