天天看點

javaScript原生bind方法的詳細解析!

前言

大家好,我是 CoderBin,在面試當中,手撕代碼的場景屢見不鮮,手寫 JS 當中的方法更是最常見的一種,是以本文将全面的,詳細解析bind方法的實作原理,并手寫出自己的bind方法,相信看完本文的小夥伴都能從中有所收獲💪。

創作不易,你們的點贊收藏留言就是我最大的動力💓

如果文中有不對、疑惑的地方,歡迎各位小夥伴們在評論區留言指正🌻

手寫 bind 方法

1. 函數作用

調用函數,可傳入參數,改變this指向,傳回一個函數可傳入參數調用得到結果

2. 總體步驟

  1. 邊界判斷(this, context)
  2. 将調用的函數設定為對象(傳入的context)的方法(改變this指向)
  3. 傳回一個函數
  4. 函數裡面:處理參數,調用函數,傳回結果

3. 詳細步驟

1. 邊界判斷

  • 判斷目前 ​

    ​this​

    ​ 是否為一個函數,否則傳回錯誤消息
  • 判斷是否傳入 ​

    ​context​

    ​​ 參數,存在則使用 ​

    ​Object()​

    ​​ 轉換為對象賦給 ​

    ​context​

    ​​,否則将 ​

    ​window​

    ​​ 指派給 ​

    ​context​

2. 将調用的函數設定為對象(傳入的context)的方法(改變this指向)

3. 調用函數,得到傳回值,并傳回

  • 調用函數,得到結果
  • 删除 ​

    ​context​

    ​​ 身上的 ​

    ​fn​

    ​ 函數
  • 傳回結果

4. 代碼實作

/**
 * !實作 binBind() 方法
 * @param {*} context 綁定的對象
 * @param  {...any} args 剩餘參數
 * @returns 
 */
Function.prototype.binBind = function(context, ...args) {
  if (typeof this !== 'function') return console.error('Error');
  context = (context!==null && context!==undefined) ? Object(context) : window

  context.fn = this // 這一步不能放在傳回的函數裡面

  // 傳回一個函數
  return function Fn(...args2) {
    // 處理參數,調用函數,傳回結果
    const newArr = [...args, ...args2]
    const result = context.fn(...newArr)
    delete context.fn
    return result
  }
}      

經過原生的bind方法和手寫的方法測試,我們手動實作的binBind方法也能實作原生bind方法的功能

需要注意的是:​

​context.fn = this​

​ 這行代碼必須放在傳回的函數外部,否則this指向會有問題!

5. 測試代碼

// 測試
function sum(num1, num2) {
  console.log(num1, num2, this);
}

// 原生的 bind() 方法
const Fn = sum.bind({ name: 'bin' }, 1)
Fn(2)

// 自定義的 binBind() 方法
const Fn1 = sum.binBind({ name: 'bin' }, 1)
Fn1(2)      

6. 細節解析

  1. 原生 ​

    ​bind()​

    ​ 方法是傳回一個函數,是以,這個手寫的函數必須也得傳回一個函數
  2. 改變 ​

    ​this​

    ​​ 指向那一步,不能放在傳回的函數中,因為函數中的 ​

    ​this​

    ​​ 指向 ​

    ​widow​

    ​;
  3. ​this​

    ​​ 指向的就是調用 ​

    ​binApply()​

    ​ 的那個函數(隐式綁定);
  4. 傳入的 ​

    ​context​

    ​​ 參數表示:将 ​

    ​this​

    ​ 的指向改為這個參數;
  5. 改變 ​

    ​this​

    ​​ 指向其實就是在 ​

    ​context​

    ​​ 上添加一個臨時的方法,值為 ​

    ​this​

    ​;
  6. 調用 ​

    ​context.fn()​

    ​​ 時,就已經改變了 ​

    ​this​

    ​ 的指向,同時得使用展開運算符傳入參數
  7. ​delete context.fn​

    ​ 删除那個臨時方法是因為已經不需要用了

7. 核心原理

繼續閱讀