溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Javascript currying柯里化是什么

發(fā)布時(shí)間:2020-12-03 13:49:52 來(lái)源:億速云 閱讀:147 作者:小新 欄目:web開(kāi)發(fā)

這篇文章主要介紹了Javascript currying柯里化是什么,具有一定借鑒價(jià)值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

面試題:實(shí)現(xiàn)add(1)(2)(3) //結(jié)果 =  6,題的核心就是問(wèn)的js的柯里化

先說(shuō)說(shuō)什么是柯里化,看過(guò)許多關(guān)于柯里化的文章,始終搞不太清楚,例如:柯里化(Currying)是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)參數(shù))的函數(shù),并且返回接受余下的參數(shù)且返回結(jié)果的新函數(shù)的技術(shù)。大多數(shù)的blog都是這種說(shuō)法,說(shuō)實(shí)話我是懵逼的。
我的理解是,curry是一個(gè)收集參數(shù)的方法,收集夠了去執(zhí)行函數(shù)。

實(shí)現(xiàn)前我們先列一下要點(diǎn)
1、收集參數(shù)(就像面試題多次執(zhí)行多個(gè)參數(shù))是的利用閉包
2、每次執(zhí)行參數(shù)有多有少例如add(1)(2,3)(4)
3、我們需要知道什么時(shí)候參數(shù)夠了

        //如題
        //add(1)(2)(3)
        //邏輯應(yīng)該是這樣add(1)執(zhí)行收集參數(shù)1繼續(xù)執(zhí)行收集參數(shù)2依次類推直到收集完畢。
       function curry(fn) {
            let arg = []; //用于收集參數(shù)
            //做一個(gè)閉包https://segmentfault.com/a/1190000017824877
            return function() {
                //每執(zhí)行一次收集一次參數(shù),為什么用concat是因?yàn)橛袝r(shí)候后是多個(gè)參數(shù)(2,3)
                arg = arg.concat([...arguments]);
                //直到參數(shù)收集完成執(zhí)行fn
                // 我們需要知道什么時(shí)候收集完了,條件就是curry參數(shù)fn的參數(shù)個(gè)數(shù) fn.length
                //如果收集的參數(shù)個(gè)數(shù)大于等于fn的參數(shù)個(gè)數(shù)執(zhí)行fn,如果沒(méi)有遞歸執(zhí)行
                if (arg.length >= fn.length) {
                    return fn(...arg)
                }
                // 參數(shù)沒(méi)有收集完我們需要繼續(xù)收集,遞歸
                return arguments.callee
            }
        }

        // 測(cè)試一下
        let testAdd = curry(add1)
        // console.log(testAdd(1)(2)(3))
        // console.log(testAdd(1, 2)(3))
        //console.log(testAdd(1)(2, 3))

一不小心寫(xiě)完了!

不過(guò)不能標(biāo)題黨,說(shuō)好的詳解,接下來(lái)我們解析一下網(wǎng)上大多數(shù)柯里化的實(shí)現(xiàn)代碼

function curry(fn) {
  function _c(restNum, argsList) {
    return restNum === 0 ?
      fn.apply(null, argsList) :
      function(x) {
        return _c(restNum - 1, argsList.concat(x));
      };
  }
  return _c(fn.length, []);
}

一眼看不明白沒(méi)事,我們多看幾眼。
解析:
1、curry也是接收一個(gè)參數(shù)(fn)這個(gè)是必然
2、返回了一個(gè)函數(shù),接收兩個(gè)參數(shù),fn.length和一個(gè)空數(shù)組這個(gè)好解
釋,我寫(xiě)的簡(jiǎn)版也說(shuō)過(guò)了,fn.length是為了判斷參數(shù)是否收集夠
了,參數(shù)傳一個(gè)空數(shù)組其實(shí)也是閉包的一種實(shí)現(xiàn),用來(lái)收集參數(shù)。
3、里邊是一個(gè)三目判斷,看著花里胡哨的沒(méi)那么復(fù)雜,判斷fn的參數(shù)個(gè)數(shù)如果是0,那就沒(méi)必要收集了直接執(zhí)行fn,至于fn.apply(null,argList)我很明白的大聲說(shuō)出來(lái)會(huì)用個(gè)apply就到處用嗎?在我看來(lái)沒(méi)有一分錢(qián)用,之所以用是因?yàn)閍rgList是一個(gè)數(shù)組,正好apply正好支持第二個(gè)參數(shù)是數(shù)組,主要看起來(lái)很牛逼的樣子。
4、收集參數(shù),fn參數(shù)個(gè)數(shù)不為零,每次收集fn函數(shù)參數(shù)的個(gè)數(shù)減一,直到等于0執(zhí)行fn,這個(gè)就沒(méi)有我寫(xiě)的通用了,我一次傳倆就掛了。

再來(lái)一個(gè)例子:bind方法實(shí)現(xiàn)

Function.prototype.bind = function(context) {
            //返回一個(gè)綁定this的函數(shù),我們需要在此保存this
            let self = this
                // 可以支持柯里化傳參,保存參數(shù)
            let arg = [...arguments].slice(1)
                // 返回一個(gè)函數(shù)
            return function() {
                //同樣因?yàn)橹С挚吕锘问絺鲄⑽覀冃枰俅潍@取存儲(chǔ)參數(shù)
                let newArg = [...arguments]
                console.log(newArg)
                    // 返回函數(shù)綁定this,傳入兩次保存的參數(shù)
                    //考慮返回函數(shù)有返回值做了return
                return self.apply(context, arg.concat(newArg))
            }
        }

        // 搞定測(cè)試
        let fn = Person.say.bind(Person1)
        fn()
        fn(18)

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享Javascript currying柯里化是什么內(nèi)容對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,遇到問(wèn)題就找億速云,詳細(xì)的解決方法等著你來(lái)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI