談談一道字節前端原題(Add sumOf)

前言

最近學弟去面了字節跳動,可是因爲面試經驗少,面試的時候緊張了,一時之間沒有寫出來,以後來我交流了一下。那我就來分析分析這道題目。javascript

image-20200906001022824

正文

這題的規則是這樣的java

給定有一個 Add 函數,要支持如下形式的調用面試

Add(1)(2)(3).sumOf(); // 輸出 6  
Add(1,2)(3)(4).sumOf(); // 輸出 10  
Add(1,2,...)(3)(4)(...).sumOf();  // ...

拿到這種題目,我先來講說我本身的作題流程,通常會去找它最簡單的形態。咱們一步一步來拆解。segmentfault

先去掉 sumOf() 變成了如下形態數組

Add(1,2,...)(3)(4)(...)

嗯....有點熟悉...可是仍是有點複雜,那咱們再去掉無限調用這個限制。微信

Add(1,2,...)(3)(4)

唔,仍是有點難呀...不要緊,再砍, 不要傳入多個參數。閉包

Add(1)(2)(3)

有....有....有那味了....這....這不就是柯里化嗎....函數

有些小朋友可能沒有聽過,對於大朋友而言耳熟能詳,融會貫通。spa

咱們仍是來介紹一下。設計

在《javascript高級程序設計》這本書中有以下介紹:

與函數綁定緊密相關的主題是函數柯里化,它用於建立已經設置好的一個或者多個參數的函數。函數柯里化的基本方法和函數綁定是同樣的:使用一個閉包返回一個函數。二者的區別在於,當函數被調用時,返回的函數還須要設置一些傳入的參數。

咱們來寫寫看:

function Add(x) {
    return function (y) {
        return return functio (z) {
            return x + y + z;
        }
    }
}
// 簡潔寫法  
const Add = x => y => z => x+y+z;

執行一下

Add(1)(2)(3) // 6

是咱們要的那味~

那麼咱們既然已經寫出了這個形態,咱們就一步一步反推。

這個時候千萬別緊張,咱們從最低級的形態出發,寫出一個最基本的形態,可以有效地幫助咱們創建自信心,吃下定心丸,按照這種方式,哪怕咱們最終沒有寫出完美的結果,讓面試官看到你思考解題的過程,也是一種加分。

好,接着說~

那咱們接下來須要實現這個樣子。

Add(1,2,...)(3)(4)

傳入參數不止一個

咱們知道,對於不肯定參數個數,咱們能夠使用 arguments 這個對象來獲取到全部的入參,可是 arguments 不是一個 Array,可是咱們能夠使用 ES6 中的 Spread syntax展開語法)去將他變成一個數組。表演繼續。

function Add() {
    const nums = [...arguments];
    return function() {
        nums.push(...arguments);
        return function() {
            nums.push(...arguments);
            return nums.reduce((a, b) => a + b);
        }
    }
}

nice!已經離咱們最終的形態愈來愈近了。接下來是這個函數可以無限的進行調用。

Add(1,2,...)(3)(4)(...)

那麼怎麼樣才能無限調用呢?沒錯,用遞歸。

function Add() {
    const nums = [...arguments];
    function AddPro() {
        nums.push(...arguments);
    return AddPro;
    }
    return AddPro;
}

嗯,其實咱們寫到這裏發現了... 因爲是無限遞歸,咱們沒辦法肯定最後一次函數調用,所以咱們須要最後顯式調用一個結束的方法來打印出最後的數據。

很天然地,咱們能夠在 AddPro 添加一個方法 sumOf 來解決這個問題。

學弟就是卡在這裏地方,被函數添加上一個方法搞懵了。你是否知道呢?
function Add() {
    const nums = [...arguments];
    function AddPro() {
        nums.push(...arguments);
    return AddPro;
    }
    AddPro.sumOf = () => {
        return nums.reduce((a, b) => a + b);
    }
    return AddPro;
}

好啦好啦,結束啦。

等等

在最後,我再來補充一種方案,function 不只能夠繼續掛載 function ~ 還能夠掛載變量哦~

function Add() {
    if (!Add.nums) {
      Add.nums = [];
  }
  Add.nums.push(...arguments);
  return Add;
}
Add.sumOf = () => {
    return Add.nums.reduce((a, b) => a + b);
}

若是上述回答有更優解,請公衆號後臺回覆,留下你的微信,紅包相送。

咱們總結一下,小小的面試題涉及到的基礎知識。

閉包、遞歸、做用域、函數與對象

基礎就是基礎,永遠是你爸爸,掌握好基礎,以不變應萬變。

一個彩蛋

function Add() {
    const nums = [...arguments];
    return () => {
        nums.push(...arguments);
        return () => {
            nums.push(...arguments);
            return nums.reduce((a, b) => a + b);
        }
    }
}
// 若是我上述代碼中間換成箭頭函數又會怎麼樣呢~

後記

也許你以爲這題有點簡單,經過簡單的重複練習就能輕鬆記住,可是最主要的是思路,不少事情都是同樣,掌握事情的方法和方向是最重要的。畢竟淘寶也不是一蹴而就的~ 可是隻要方向正確了,都會好起來的。

最後

若是個人文章有幫助到你,但願你也能幫助我,歡迎關注個人微信公衆號 秋風的筆記,回覆好友 二次,可加微信而且加入交流羣,秋風的筆記 將一直陪伴你的左右。

image

相關文章
相關標籤/搜索