欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS中函數(shù)科里化的背景與應(yīng)用實(shí)例教程

 更新時(shí)間:2022年06月06日 09:16:11   作者:程序媛徐嬋  
在數(shù)學(xué)和計(jì)算機(jī)科學(xué)中,柯里化是一種將使用多個(gè)參數(shù)的一個(gè)函數(shù)轉(zhuǎn)換成一系列使用一個(gè)參數(shù)的函數(shù)的技術(shù),下面這篇文章主要給大家介紹了JS中函數(shù)科里化的背景與應(yīng)用實(shí)例的相關(guān)資料,需要的朋友可以參考下

背景

柯里化(Currying)是一種關(guān)于函數(shù)的高階技術(shù)。它不僅被用于 JavaScript,還被用于其他編程語(yǔ)言。函數(shù)柯里化又叫部分求值,維基百科中對(duì)柯里化 (Currying) 的定義為:

在數(shù)學(xué)和計(jì)算機(jī)科學(xué)中,柯里化是一種將使用多個(gè)參數(shù)的函數(shù)轉(zhuǎn)換成一系列使用一個(gè)參數(shù)的函數(shù),并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)。

用大白話來說就是只傳遞給函數(shù)一部分參數(shù)來調(diào)用它,讓它返回一個(gè)新函數(shù)去處理剩下的參數(shù)。使用一個(gè)簡(jiǎn)單的例子來介紹下,最常用的就是 add 函數(shù)了。

// add method
const add = (...args) => args.reduce((a, b) => a + b);

// 傳入多個(gè)參數(shù),執(zhí)行 add 函數(shù)
add(1, 2) // 返回 3

// 假設(shè)我們實(shí)現(xiàn)了一個(gè) currying 函數(shù),支持一次傳入一個(gè)參數(shù)
let sum = currying(add);
let addCurryOne = sum(1);
addCurryOne(2) // 返回 3
addCurryOne(3) // 返回 4

使用場(chǎng)景

柯里化是一種函數(shù)的轉(zhuǎn)換,它是指將一個(gè)函數(shù)從可調(diào)用的 f(a, b, c) 轉(zhuǎn)換為可調(diào)用的 f(a)(b)(c)。柯里化不會(huì)調(diào)用函數(shù)。它只是對(duì)函數(shù)進(jìn)行轉(zhuǎn)換。 在平常工作中主要使用場(chǎng)景如下:

  • 1、延遲計(jì)算(部分求和、bind 函數(shù))

  • 2、動(dòng)態(tài)創(chuàng)建函數(shù)(添加監(jiān)聽 addEvent、惰性函數(shù))

  • 3、參數(shù)復(fù)用(Function.prototype.call.bind(Object.prototype.toString))

JS中的函數(shù)科里化

可以對(duì)比下haskell這種天然的函數(shù)式語(yǔ)言,js里的珂里化實(shí)在是殘缺不全...但是利用珂里化這種參數(shù)對(duì)應(yīng)函數(shù)的思想,結(jié)合js的閉包特性,來實(shí)現(xiàn)良好的封裝。 舉個(gè)例子:js中最常見的dom的插入和刪除。 普通寫法:變量都在外部,不能確保每個(gè)remove操作都“正確”的

var append = function (parent, child) {
    parent.appendChild(child);
}
var remove = function (dom) {
    dom.remove();
}
//插入 remove(child); //刪除
append(parent, child); 

文藝寫法:確保了每個(gè)刪除操作都會(huì)刪除插入的節(jié)點(diǎn)。

var append = function (parent, child) {
    parent.appendChild(child);
    return function () {
        child.remove();
    }
}

//或者是這種,point free風(fēng)格 
var append2 = function (parent, child) {
    parent.appendChild(child);
    return child.remove.bind(child);
}
//插入一個(gè)節(jié)點(diǎn),同時(shí)返回所插入的節(jié)點(diǎn)的刪除操作。 remove(); //刪除。
var remove = append(parent, child);

總結(jié)一下就是說,這種以函作為主體,確保了函數(shù)之間不會(huì)相互干擾,尤其是在復(fù)雜的前端工程下,每一處的代碼越“安全”,越獨(dú)立,越能更好的拓展功能和排查問題。

經(jīng)典面試題:add(1)(2)(3)

function add(seed) {
    function retVal(later) {
        return add(seed + later);
    }
    retVal.toString = function () {
        return seed;
    };
    return retVal;
}
console.log(add(1)(2)(3).toString()); // 6

add函數(shù)返回閉包retVal,在retVal中又繼續(xù)調(diào)用add,最終我們可以寫成add(1)(2)(3)(...)這樣柯里化的形式。 每調(diào)用一次add函數(shù),都會(huì)返回retValue函數(shù);調(diào)用retValue函數(shù)會(huì)調(diào)用add函數(shù),然后還是返回retValue函數(shù),所以調(diào)用add的結(jié)果一定是返回一個(gè)retValue函數(shù)。add函數(shù)的存在意義只是為了提供閉包,這個(gè)類似的遞歸調(diào)用每次調(diào)用add都會(huì)生成一個(gè)新的閉包。

總結(jié)

優(yōu)點(diǎn):

  • 參數(shù)復(fù)用
  • 提前返回
  • 延遲計(jì)算/運(yùn)行

缺點(diǎn):

  • 函數(shù)柯里化可以用來構(gòu)建復(fù)雜的算法 和 功能, 但是濫用也會(huì)帶來額外的開銷。從上面實(shí)現(xiàn)部分的代碼中,可以看到,使用柯里化函數(shù),離不開閉包, arguments, 遞歸。
  • 閉包,函數(shù)中的變量都保存在內(nèi)存中,內(nèi)存消耗大,有可能導(dǎo)致內(nèi)存泄漏。
  • 遞歸,效率非常
  • arguments, 變量存取慢,訪問性很差

我個(gè)人覺得柯里化并非是必須的,而且不熟悉的同學(xué)閱讀起來可能會(huì)遇到麻煩,但是它能幫助我們理解JS中的函數(shù)式編程,更重要的是,我們以后在閱讀類似的代碼時(shí),不會(huì)感到陌生。

并非“柯里化”對(duì)函數(shù)式編程有意義。而是,函數(shù)式編程在把函數(shù)當(dāng)作一等公民的同時(shí),就不可避免的會(huì)產(chǎn)生“柯里化”這種用法。所以它并不是因?yàn)?ldquo;有什么意義”才出現(xiàn)的。

到此這篇關(guān)于JS中函數(shù)科里化的背景與應(yīng)用的文章就介紹到這了,更多相關(guān)JS函數(shù)科里化應(yīng)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論