1. 程式人生 > 其它 >理解並手寫 call() 函式

理解並手寫 call() 函式

手寫自己的call,我們要先通過call的使用,瞭解都需要完成些什麼功能?

call()進行了呼叫,肯定是個方法,已知是建立在原型上的,使用了多個引數(繫結的物件+傳遞的引數)。

我們把手寫的函式起名為myCall,把context物件作為傳遞的引數集。

Function.prototype.myCall = function(context){}

call的呼叫對this的指向進行了改變,而this是函式,這是前提(對this進行判斷)。

Funtion.prototype.myCall = function(context){
  // 判斷呼叫物件
  if(typeof this !== 'function'){
    console.error(
'type error')   } }

同理應當判斷是否傳入了引數,如果沒有傳入引數則設定為window。

Funtion.prototype.myCall = function(context){
  if(typeof this !== 'function'){
    console.error('type error')
    }
  // 判斷傳遞引數
  context = context || window;
}

要呼叫這個this方法,我們可以先將其作為物件的屬性方法,然後呼叫。

Function.prototype.myCall = function(context){
  
if(typeof this !== 'function'){     console.error('type error!');   }   context = context || window;   // 新增屬性方法,並呼叫   context.fn = this;   context.fn(); }

call呼叫完後,擁有使用完方法後的返回值,所以肯定要將方法的執行結果儲存並返回。

Function.prototype.mycall = function(context){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  context 
= context || window;   context.fn = this;   // 將執行結果儲存,並返回   let result = context.fn();   return result; }

在原物件中,並沒有context.fn屬性,所以我們要將其進行刪除。

Function.prototype.mycall = function(context){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  context = context || window;
  context.fn = this;
  let result = context.fn();
  // 刪除context.fn屬性
  delete context.fn;
  return result;
}

最後考慮下我們方法中傳遞的引數,引數是由context物件的第二個元素開始的,通過slice()進行切割。

Function.prototype.mycall = function(context){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  // 獲取正確引數
  let args = [...arguments].slice(1)
  context = context || window;
  context.fn = this;
  let result = context.fn(...args);
  delete context.fn;
  return result;
}

最後通過一個例子,來驗證是否達到call()的功能要求。

Function.prototype.myCall = function(context) {
  if (typeof this !== 'function') {
    console.error('type error!');
  }
  context = context || window;
  let args = [...arguments].slice(1);
  context.fn = this;
  let result = context.fn(...args)
  delete context.fn;
  return result;
}
let dog = {
  name: '狗',
  eat(food1, food2) {
    console.log(this.name + '愛吃' + food1 + food2);
  }
}
let cat = {
  name: '貓',
}
dog.eat.call(cat, '魚', '肉');     // 貓愛吃魚肉
dog.eat.myCall(cat, '魚', '肉');   // 貓愛吃魚肉

本文來自部落格園,作者:HuiTaiLang1216,轉載請註明原文連結:https://www.cnblogs.com/HuiTaiLang1216/p/15974486.html