網易面試官:請你實現一下JS過載?可不是TS過載哦!

Sunshine_Lin發表於2021-12-01

前言

大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎是進階的前提是我的初心。今天給大家講一道題,是一道網易的面試題

  • 一位同學:“如何實現JS過載?”
  • 我:“JS有過載嗎?不是TS才有嗎?”
  • 一位同學:“有的,這是網易一道面試題”
  • 我:“好吧我想想哈!”

image.png

什麼是過載

我第一次看到 過載 這個詞還是在以前學習 Java 的時候,我一直覺得 JavaScript 是沒有過載的,直到 TypeScript 的出現,所以我一直覺得 JavaScript 沒有過載, TypeScript 才有,但是現在看來我是錯的。

我理解的過載是:同樣的函式,不同樣的引數個數,執行不同的程式碼,比如:

/*
* 過載
*/
function fn(name) {
  console.log(`我是${name}`)
}

function fn(name, age) {
  console.log(`我是${name},今年${age}歲`)
}

function fn(name, age, sport) {
  console.log(`我是${name},今年${age}歲,喜歡運動是${sport}`)
}

/*
* 理想結果
*/
fn('林三心') // 我是林三心
fn('林三心', 18) // 我是林三心,今年18歲
fn('林三心', 18, '打籃球') // 我是林三心,今年18歲,喜歡運動是打籃球

但是直接在 JavaScript 中這麼寫,肯定是不行的,我們們來看看上面程式碼的實際執行結果,可以看到,最後一個 fn 的定義,把前面兩個都給覆蓋了,所以沒有實現 過載 的效果

我是林三心,今年undefined歲,喜歡運動是undefined
我是林三心,今年18歲,喜歡運動是undefined
我是林三心,今年18歲,喜歡運動是打籃球

我的做法

其實,想要實現理想的 過載 效果,我還是有辦法的,我可以只寫一個 fn 函式,並在這個函式中判斷 arguments 類陣列的長度,執行不同的程式碼,就可以完成 過載 的效果

function fn() {
  switch (arguments.length) {
    case 1:
      var [name] = arguments
      console.log(`我是${name}`)
      break;
    case 2:
      var [name, age] = arguments
      console.log(`我是${name},今年${age}歲`)
      break;
    case 3:
      var [name, age, sport] = arguments
      console.log(`我是${name},今年${age}歲,喜歡運動是${sport}`)
      break;
  }
}

/*
* 實現效果
*/
fn('林三心') // 我是林三心
fn('林三心', 18) // 我是林三心,今年18歲
fn('林三心', 18, '打籃球') // 我是林三心,今年18歲,喜歡運動是打籃球

但是那位同學說,網易的面試官好像覺得這麼實現可以是可以,但是還有沒有更好的實現方法,我就懵逼了。

高階做法

image.png

經過了我的一通網上查詢資料,發現了一種比較高階的做法,可以利用 閉包 來實現 過載 的效果。這個方法在JQuery之父John Resig寫的《secrets of the JavaScript ninja》中,這種方法充分的利用了 閉包 的特性!

function addMethod(object, name, fn) {
  var old = object[name]; //把前一次新增的方法存在一個臨時變數old裡面
  object[name] = function () { // 重寫了object[name]的方法
    // 如果呼叫object[name]方法時,傳入的引數個數跟預期的一致,則直接呼叫
    if (fn.length === arguments.length) {
      return fn.apply(this, arguments);
      // 否則,判斷old是否是函式,如果是,就呼叫old
    } else if (typeof old === "function") {
      return old.apply(this, arguments);
    }
  }
}

addMethod(window, 'fn', (name) => console.log(`我是${name}`))
addMethod(window, 'fn', (name, age) => console.log(`我是${name},今年${age}歲`))
addMethod(window, 'fn', (name, age, sport) => console.log(`我是${name},今年${age}歲,喜歡運動是${sport}`))

/*
* 實現效果
*/

window.fn('林三心') // 我是林三心
window.fn('林三心', 18) // 我是林三心,今年18歲
window.fn('林三心', 18, '打籃球') // 我是林三心,今年18歲,喜歡運動是打籃球

結語

如果你覺得此文對你有一丁點幫助,點個贊,鼓勵一下林三心哈哈。或者可以加入我的摸魚群,我們一起好好學習啊啊啊啊啊啊啊,我會定時模擬面試,簡歷指導,答疑解惑,我們們互相學習共同進步!!
截圖2021-11-28 上午9.43.19.png

參考資料

相關文章