面試題 - 實現一個 call/apply 方法

面試題 - 實現一個 call/apply 方法

題目

實現一個 call / apply 方法。

解析

call 和 apply 方法一個重要的特徵就是第一個參數可以綁定 this 指向。如下案例:

var a = 100;
var obj = {
  a:1000;
}
function fun(){
  console.log(this.a);//1000
}
fun.call(obj);

如上所示,如果沒有使用 call 方法顯式地將 obj 對象綁定到 this。fun 函數中 this 指向的就是 window。而 apply 與 call 的區別就是 apply 方法從第二參數開始是以數組的形式傳參。

實現 call/apply 方法有兩個關鍵點:

  1. 綁定 this。this 指向問題可以用一句話概括,“誰調用,this 就指向誰”。所以綁定 this 就需要將調用的方法添加到傳過來的對象上去。再通過對象去調用。這樣就可以實現將 this 指向這個對象。
    即結合以上案例可以簡單地理解爲是將 fun 方法添加到 obj 對象的屬性上。然後通過 obj 對象的屬性去調用 fun 方法,就可以實現 fun 中的 this 指向 obj。

  2. 傳遞參數。除了將方法添加到對象上,還需要將參數進行傳遞。傳遞參數可以有三種方式, apply,eval(循壞數組,拼接字符串),ES6 的數組解構。以下案例中使用的是 ES6 的數組解構。

代碼

實現一個 call 方法

Function.prototype._call = function(){
	  //1.將第一個參數(綁定this的對象)和剩餘參數解構出來
	  let [thisObj,...arg] = [...arguments];
	  //2.如果第一個參數爲空,則this爲全局對象
      if(!thisObj){
          thisObj = typeof window === 'undefined'? global:window;
      }
      //3.把this(調用_call的方法) 賦值到該對象的一個屬性上
      thisObj._this = this;
      //4.調用對象綁定的方法。
      var result = thisObj._this(...arg);
      //5.刪除綁定的屬性
      delete thisObj._this;
      //6.返回調用結果
      return result;
    }
    
    //測試
    var num = 18;
    function Person(a,b) {       
        console.log(this.num + a + b);//60
    }
    var obj = {     
        num:20
    }
    Person._call(obj,20,20);

實現一個 apply 方法。

Function.prototype._apply = function(){
	  //1.將第一個參數(綁定this的對象)和數組參數(這裏是apply與call的區別)解構出來
	  let [thisObj,arg] = [...arguments];
	  //2.如果第一個參數爲空,則this爲全局對象
      if(!thisObj){
          thisObj = typeof window === 'undefined'? global:window;
      }
      //3.把this(調用_apply的方法) 賦值到該對象的一個屬性上
      thisObj._this = this;
      //4.調用對象綁定的方法。
      var result;
      if(arg){
	      if(!Array.isArray(arg)){
	         throw new Error("參數爲數組")
	      }else{
	         result = thisObj._this(...arg);
	      }
      }else {
          result = thisObj._this();
      }
      //5.刪除綁定的屬性
      delete thisObj._this;
      //6.返回調用結果
      return result;
    }
   
    //測試
    var num = 18;
    function Person(a,b) {       
        console.log(this.num + a + b);//60
    }
    var obj = {     
        num:20
    }
    Person._apply(obj,[20,20]);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章