亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

從一道面試題認識函數(shù)柯里化

13651657101 / 1982人閱讀

摘要:函數(shù)柯里化在函數(shù)式編程中,函數(shù)是一等公民。函數(shù)柯里化的主要作用和特點就是參數(shù)復(fù)用提前返回和延遲執(zhí)行。可能在實際應(yīng)用場景中,很少使用函數(shù)柯里化的解決方案,但是了解認識函數(shù)柯里化對自身的提升還是有幫助的。

最近在整理面試資源的時候,發(fā)現(xiàn)一道有意思的題目,所以就記錄下來。

題目

如何實現(xiàn) multi(2)(3)(4)=24?

首先來分析下這道題,實現(xiàn)一個 multi 函數(shù)并依次傳入?yún)?shù)執(zhí)行,得到最終的結(jié)果。通過題目很容易得到的結(jié)論是,把傳入的參數(shù)相乘就能夠得到需要的結(jié)果,也就是 2X3X4 = 24。

簡單的實現(xiàn)

那么如何實現(xiàn) multi 函數(shù)去計算出結(jié)果值呢?腦海中首先浮現(xiàn)的解決方案是,閉包。

function multi(a) {
    return function(b) {
        return function(c) {
            return a * b * c;
        }
    }
}

利用閉包的原則,multi 函數(shù)執(zhí)行的時候,返回 multi 函數(shù)中的內(nèi)部函數(shù),再次執(zhí)行的時候其實執(zhí)行的是這個內(nèi)部函數(shù),這個內(nèi)部函數(shù)中接著又嵌套了一個內(nèi)部函數(shù),用于計算最終結(jié)果并返回。

單純從題面來說,似乎是已經(jīng)實現(xiàn)了想要的結(jié)果,但仔細一想就會發(fā)現(xiàn)存在問題。

上面的實現(xiàn)方案存在的缺陷:

代碼不夠優(yōu)雅,實現(xiàn)步驟需要一層一層的嵌套函數(shù)。

可擴展性差,假如是要實現(xiàn) multi(2)(3)(4)...(n) 這樣的功能,那就得嵌套 n 層函數(shù)。

那么有沒有更好的解決方案,答案是,使用函數(shù)式編程中的函數(shù)柯里化實現(xiàn)。

函數(shù)柯里化

在函數(shù)式編程中,函數(shù)是一等公民。那么函數(shù)柯里化是怎樣的呢?

函數(shù)柯里化指的是將能夠接收多個參數(shù)的函數(shù)轉(zhuǎn)化為接收單一參數(shù)的函數(shù),并且返回接收余下參數(shù)且返回結(jié)果的新函數(shù)的技術(shù)。

函數(shù)柯里化的主要作用和特點就是參數(shù)復(fù)用、提前返回和延遲執(zhí)行。

例如:封裝兼容現(xiàn)代瀏覽器和 IE 瀏覽器的事件監(jiān)聽的方法,正常情況下封裝是這樣的。

var addEvent = function(el, type, fn, capture) {
    if(window.addEventListener) {
        el.addEventListener(type, function(e) {
            fn.call(el, e);
        }, capture);
    }else {
        el.attachEvent("on" + type, function(e) {
            fn.call(el, e);
        })
    }
}

該封裝的方法存在的不足是,每次寫監(jiān)聽事件的時候調(diào)用 addEvent 函數(shù),都會進行 if else 的兼容性判斷。事實上在代碼中只需要執(zhí)行一次兼容性判斷就可以了,后續(xù)的事件監(jiān)聽就不需要再去判斷兼容性了。那么怎么用函數(shù)柯里化優(yōu)化這個封裝函數(shù)。

var addEvent = (function() {
    if(window.addEventListener) {
        return function(el, type, fn, capture) {
            el.addEventListener(type, function(e) {
                fn.call(el, e);
            }, capture);
        }
    }else {
        return function(ele, type, fn) {
            el.attachEvent("on" + type, function(e) {
                fn.call(el, e);
            })
        }
    }
})()

js 引擎在執(zhí)行該段代碼的時候就會進行兼容性判斷,并且返回需要使用的事件監(jiān)聽封裝函數(shù)。這里使用了函數(shù)柯里化的兩個特點:提前返回和延遲執(zhí)行。

柯里化另一個典型的應(yīng)用場景就是 bind 函數(shù)的實現(xiàn)。使用了函數(shù)柯里化的兩個特點:參數(shù)復(fù)用和提前返回。

Function.prototype.bind = function(){
    var fn = this;
    var args = Array.prototye.slice.call(arguments);
    var context = args.shift();

    return function(){
        return fn.apply(context, args.concat(Array.prototype.slice.call(arguments)));
    };
};
柯里化的實現(xiàn)

那么如何通過函數(shù)柯里化實現(xiàn)面試題的功能呢?

通用版
function curry(fn) {
    var args = Array.prototype.slice.call(arguments, 1);
    return function() {
        var newArgs = args.concat(Array.prototype.slice.call(arguments));
        return fn.apply(this, newArgs);
    }
}

curry 函數(shù)的第一個參數(shù)是要動態(tài)創(chuàng)建柯里化的函數(shù),余下的參數(shù)存儲在 args 變量中。

執(zhí)行 curry 函數(shù)返回的函數(shù)接收新的參數(shù)與 args 變量存儲的參數(shù)合并,并把合并的參數(shù)傳入給柯里化了的函數(shù)。

function multiFn(a, b, c) {
    return a * b * c;
}
var multi = curry(multiFn);
multi(2,3,4);

結(jié)果:

雖然得到的結(jié)果是一樣的,但是很容易發(fā)現(xiàn)存在問題,就是代碼相對于之前的閉包實現(xiàn)方式較復(fù)雜,而且執(zhí)行方式也不是題目要求的那樣 multi(2)(3)(4)。那么下面就來改進這版代碼。

改進版

就題目而言,是需要執(zhí)行三次函數(shù)調(diào)用,那么針對柯里化后的函數(shù),如果傳入的參數(shù)沒有 3 個的話,就繼續(xù)執(zhí)行 curry 函數(shù)接收參數(shù),如果參數(shù)達到 3 個,就執(zhí)行柯里化了的函數(shù)。

function curry(fn, args) {
    var length = fn.length;
    var args = args || [];
    return function(){
        newArgs = args.concat(Array.prototype.slice.call(arguments));
        if(newArgs.length < length){
            return curry.call(this,fn,newArgs);
        }else{
            return fn.apply(this,newArgs);
        }
    }
}
function multiFn(a, b, c) {
    return a * b * c;
}
var multi = curry(multiFn);
multi(2)(3)(4);
multi(2,3,4);
multi(2)(3,4);
multi(2,3)(4);

可以看到,通過改進版的柯里化函數(shù),已經(jīng)將題目定的實現(xiàn)方式擴展到好幾種了。這種實現(xiàn)方案的代碼擴展性就比較強了,但是還是有點不足,就是必須事先知道求值的參數(shù)個數(shù),那能不能讓代碼更靈活點,達到隨意傳參的效果,例如: multi(2)(3)(4),multi(5)(6)(7)(8)(9) 這樣的。

優(yōu)化版
function multi() {
    var args = Array.prototype.slice.call(arguments);
    var fn = function() {
        var newArgs = args.concat(Array.prototype.slice.call(arguments));
        return multi.apply(this, newArgs);
    }
    fn.toString = function() {
        return args.reduce(function(a, b) {
            return a * b;
        })
    }
    return fn;
}

這樣的解決方案就可以靈活的使用了。不足的是返回值是 Function 類型。

總結(jié)

就題目本身而言,是存在多種實現(xiàn)方式的,只要理解并充分利用閉包的強大。

可能在實際應(yīng)用場景中,很少使用函數(shù)柯里化的解決方案,但是了解認識函數(shù)柯里化對自身的提升還是有幫助的。

理解閉包和函數(shù)柯里化之后,如果在面試中遇到類似的題型,應(yīng)該就可以迎刃而解了。

后記

本著學(xué)習(xí)和總結(jié)的態(tài)度寫的技術(shù)輸出,文中有任何錯誤和問題,請大家指出。更多的技術(shù)輸出可以查看我的 github博客。

整理了一些前端的學(xué)習(xí)資源,希望能夠幫助到有需要的人,地址: 學(xué)習(xí)資源匯總。

參考

https://segmentfault.com/q/10...

https://blog.csdn.net/crystal...

https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651228431&idx=1&sn=c9d62a30a52f4572cc0cb4aaf2a82ef3

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/97071.html

相關(guān)文章

  • 一道面試談?wù)?em>函數(shù)柯里(Currying)

    摘要:忍者秘籍一書中,對于柯里化的定義如下在一個函數(shù)中首先填充幾個參數(shù)然后再返回一個新函數(shù)的技術(shù)稱為柯里化。回到我們的題目本身,其實根據(jù)測試用例我們可以發(fā)現(xiàn),函數(shù)的要求就是接受單一函數(shù),例如但是與柯里化不同之處在于,柯里化返回的一個新函數(shù)。   歡迎大家再一次來到我的文章專欄:從面試題中我們能學(xué)到什么,各位同行小伙伴是否已經(jīng)開始了悠閑的春節(jié)假期呢?在這里提前祝大家雞年大吉吧~哈哈,之前有人說...

    cppprimer 評論0 收藏0
  • 一道柯里面試

    摘要:這是一道朋友在群里發(fā)的一道題,我之前不是很懂柯里化,就自己試著寫了一下,不知道算不算柯里化,望指教下面是題目寫好之后一下代碼可以正常運行輸入正確我自己的代碼我用到了以下知識點擴展運算符傳參和擴展運算符相關(guān)的數(shù)組操作。 這是一道朋友在群里發(fā)的一道題,我之前不是很懂柯里化,就自己試著寫了一下,不知道算不算柯里化,望指教~ 下面是題目: function curry() { ...

    andycall 評論0 收藏0
  • 「前端面試系列6」理解函數(shù)柯里

    摘要:原題如下寫一個方法,當使用下面的語法調(diào)用時,能正常工作這道題要考察的,就是對函數(shù)柯里化的理解。當參數(shù)只有一個的時候,進行柯里化的處理。這其實就是函數(shù)柯里化的簡單應(yīng)用。 showImg(https://segmentfault.com/img/bVbopGm?w=620&h=350); 前言 這是前端面試題系列的第 6 篇,你可能錯過了前面的篇章,可以在這里找到: ES6 中箭頭函數(shù)的...

    liaorio 評論0 收藏0
  • 關(guān)于JavaScript函數(shù)柯里探索

    摘要:函數(shù)柯里化關(guān)于函數(shù)柯里化的問題最初是在忍者秘籍中講閉包的部分中看到的,相信很多同學(xué)見過這樣一道和柯里化有關(guān)的面試題實現(xiàn)一個函數(shù),使得如下斷言能夠能夠通過簡單說就是實現(xiàn)一個求值函數(shù),能夠?qū)⑺袇?shù)相加得出結(jié)果。方法返回一個表示該對象的字符串。 函數(shù)柯里化 ??關(guān)于函數(shù)柯里化的問題最初是在《JavaScript忍者秘籍》中講閉包的部分中看到的,相信很多同學(xué)見過這樣一道和柯里化有關(guān)的面試題:...

    vboy1010 評論0 收藏0
  • 面試函數(shù)柯里

    摘要:題目發(fā)現(xiàn)一道有意思的面試題如何實現(xiàn)首先簡單分析一下,我們就能發(fā)現(xiàn)這是一個函數(shù)傳值次得到。簡單實現(xiàn)利用閉包,執(zhí)行函數(shù)時一個匿名函數(shù),用于最終返回結(jié)果。當然,這個方法有個明顯缺陷,就是如果函數(shù)變成,我們就又要手動嵌套一層。 題目 發(fā)現(xiàn)一道有意思的面試題:如何實現(xiàn) add(1)(2)(3)=6 ? 首先簡單分析一下,我們就能發(fā)現(xiàn)這是一個函數(shù)傳值 return3次得到6 。 簡單實現(xiàn) func...

    wudengzan 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<