前端經典面試題解密-add(1)(2)(3)(4) == 10到底是個啥?

寫在前面:本期教程算是個經常會遇到的面試題,更多的前端視頻教程也會繼續給大家出,文末有給大家總結有相關的視頻學習教程,大家按需自行學習哈!不全的地方,大家可以留言或私我,我再發。

前端的小夥伴在面試的時候,幾乎都會遇到一道這樣的面試題: add(1)(2)(3)(4)輸出結果為10。在第一次看到這道面試題的時候,很多小夥伴感到了迷茫!借用王寶強在《人在囧途》中的表演:啥啥啥,這寫的都是啥?下面為各位小夥伴帶來這道題的揭秘。


前端經典面試題解密-add(1)(2)(3)(4) == 10到底是個啥?


一、核心點-基礎函數的變種-函數柯里化

我們從0開始,一點點兒的觀察。add(1)(2)(3)(4)輸出的值怎麼成為10,很簡單,大家都明白是1+2+3+4的累加。那使用基礎函數是怎麼實現的呢?

<code>function add (a, b, c, d) {
    return a + b + c + d
}
add(1, 2, 3, 4) // 10
/<code>

那如何add(1)(2)(3)(4)如何也輸出10呢?小夥伴接下來可能會想到這樣:

<code>function add (a) {
    return function (b) {
        return function (c) {
            return function (d) {
                return a + b + c + d
            }
        }
    }
}
/<code>

是不是很完美!

但是如果你這麼回答面試官,面試官肯定會立刻懟死你,累加到100怎麼辦?(PS:沒有說10000已經很客氣了)

你老師經典語錄:下面的是重點,圈起來,一定要考!!

函數柯里化概念: 柯里化(Currying)是把接受多個參數的函數轉變為接受一個單一參數的函數,並且返回接受餘下的參數且返回結果的新函數的技術。

二、函數柯里化解決方案

函數柯里化有兩種不同的場景,一種為函數參數個數定長的函數,另外一種為函數參數個數不定長的函數。

1.函數參數個數定長的柯里化解決方案

<code>// 定長參數
function add (a, b, c, d) {
    return [
      ...arguments
    ].reduce((a, b) => a + b)
}
 
function currying (fn) {
    let len = fn.length
    let args = []
    return function _c (...newArgs) {
        // 合併參數
        args = [
            ...args,
            ...newArgs
        ]
        // 判斷當前參數集合args的長度是否 < 目標函數fn的需求參數長度
        if (args.length < len) {
            // 繼續返回函數
            return _c
        } else {
            // 返回執行結果
            return fn.apply(this, args.slice(0, len))
        }
    }
}
let addCurry = currying(add)
let total = addCurry(1)(2)(3)(4) // 同時支持addCurry(1)(2, 3)(4)該方式調用
console.log(total) // 10
/<code>

2.函數參數個數不定長的柯里化解決方案

問題升級:那這個問題再升級一下,函數的參數個數不確定時,如何實現呢?

<code>function add (...args) {
    return args.reduce((a, b) => a + b)
}
 
function currying (fn) {
    let args = []
    return function _c (...newArgs) {
        if (newArgs.length) {
            args = [
                ...args,
                ...newArgs
            ]
            return _c
        } else {
            return fn.apply(this, args)
        }
    }
}
 
let addCurry = currying(add)
// 注意調用方式的變化
console.log(addCurry(1)(2)(3)(4, 5)())
/<code>

最後:有不清楚的地方,夥伴們可以留言,今天的教程先到這裡,另外給夥伴們些乾貨,可以私下給自己鍍鍍金!


分享到:


相關文章: