詳解JS中 call 方法的實現

語言: CN / TW / HK

摘要: 本文將全面的,詳細解析call方法的實現原理

本文分享自華為雲社群《 關於 JavaScript 中 call 方法的實現,附帶詳細解析! 》,作者:CoderBin。

本文將全面的,詳細解析call方法的實現原理,並手寫出自己的call方法,相信看完本文的小夥伴都能從中有所收穫。

call 方法的實現

1.函式作用

呼叫函式,可傳入引數,改變this指向

2.總體步驟

  1. 邊界判斷(this,context)
  2. 將呼叫的函式設定為物件(傳入的context)的方法(改變this指向)
  3. 呼叫函式,得到返回值,並返回

3. 詳細步驟

1. 邊界判斷

  • 判斷當前 this 是否為一個函式,否則返回錯誤訊息
  • 判斷傳入的 context 引數是否存在,存在則使用 Object() 轉換為物件賦給 context,否則將 window 賦值給 context

2. 將呼叫的函式設定為物件(傳入的context)的方法(改變this指向)

3. 呼叫函式,得到返回值,並返回

  • 呼叫函式,得到結果
  • 刪除 context 身上的 fn 函式
  • 返回結果

4. 程式碼實現

/**
 * !實現 binCall() 方法
 * @param {*} context 繫結的物件
 * @param  {...any} args 剩餘引數
 * @returns 
 */
Function.prototype.binCall = function(context, ...args) {
 if (typeof this !== 'function') console.error('type Error'); // 1
  context = (context!==null && context!==undefined) ? Object(context) : window
 context.fn = this // 2
 const result = context.fn(...args) // 3
 delete context.fn;
 return result
}

5. 測試程式碼

// 測試
function sum(num1, num2) {
  console.log('sum 被執行', this);
 return num1 + num2
}
// 原生的 call() 方法
console.log(sum.call({name: 'bin'},1,2));
// 自定義的 binCall() 方法
console.log(sum.binCall({name: 'bin'},1,2));

經過原生的call方法和手寫的binCall方法測試,我們手動實現的binCall方法也能實現原生call方法的功能

6. 細節解析

  1. this 指向的就是呼叫 binCall() 的那個函式(隱式繫結);
  2. 傳入的 context 引數表示:將 this 的指向改為這個引數;
  3. 改變 this 指向其實就是在 context 上新增一個臨時的方法,值為 this;
  4. 呼叫 context.fn() 時,就已經改變了 this 的指向,同時得使用展開運算子傳入引數
  5. delete context.fn 刪除那個臨時方法是因為已經不需要用了

7. 核心原理

通過在傳入的物件上,臨時新增一個方法,這個方法的值是當前 binCall 的呼叫者。然後 context.fn(...argArray) 呼叫這個函式,通過隱式繫結的方式改變了 this 的指向,最後得到結果並返回。

點選關注,第一時間瞭解華為雲新鮮技術~