理解並手寫 call() 函式
阿新 • • 發佈:2022-03-07
手寫自己的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