最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS函數(shù)式編程之純函數(shù)、柯里化以及組合函數(shù)

 更新時間:2023年01月08日 11:55:30   作者:虛幻私塾  
這篇文章主要介紹了JS函數(shù)式編程之純函數(shù)、柯里化以及組合函數(shù),文章對三個函數(shù)進行分析講解,內(nèi)容也很容易理解,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

前言

函數(shù)式編程(Functional Programming),又稱為泛函編程,是一種編程范式。

早在很久以前就提出了函數(shù)式編程這個概念了,而后面一直長期被面向?qū)ο缶幊趟y(tǒng)治著,最近幾年函數(shù)式編程又回到了大家的視野中,JavaScript是一門以函數(shù)為第一公民的語言,必定是支持這一種編程范式的。

下面就來談?wù)凧avaScript函數(shù)式編程中的核心概念純函數(shù)、柯里化以及組合函數(shù)。

純函數(shù)

純函數(shù)的概念

對于純函數(shù)的定義,維基百科中是這樣描述的:在程序設(shè)計中,若函數(shù)符合以下條件,那么這個函數(shù)被稱之為純函數(shù)。

  • 此函數(shù)在相同的輸入值時,需產(chǎn)生相同的輸出;
  • 函數(shù)的輸入和輸出值以外的其他隱藏信息或狀態(tài)無關(guān),也和由I/O設(shè)備產(chǎn)生的外部輸出無關(guān);
  • 該函數(shù)不能有語義上可觀察的函數(shù)副作用,諸如“觸發(fā)事件”,使輸出設(shè)備輸出,或更改輸出值以外物件的內(nèi)容等;

對以上描述總結(jié)就是:

  • 對于相同的輸入,永遠會得到相同的輸出;
  • 在函數(shù)的執(zhí)行過程中,沒有任何可觀察的副作用;
  • 同時也不依賴外部環(huán)境的狀態(tài);

副作用

上面提到了一個詞叫“副作用”,那么什么是副作用呢?

  • 通常我們所說的副作用大多數(shù)是指藥會產(chǎn)生的副作用;
  • 而在計算機科學(xué)中,副作用指在執(zhí)行一個函數(shù)時,除了得到函數(shù)的返回值以外,還在函數(shù)調(diào)用時產(chǎn)生了附加的影響,比如修改了全局變量的狀態(tài),修改了傳入的參數(shù)或得到了其它的輸出內(nèi)容等;

純函數(shù)案例

  • 編寫一個求和的函數(shù)sum,只要我們輸入了固定的值,sum函數(shù)就會給我們返回固定的結(jié)果,且不會產(chǎn)生任何副作用。
function sum(a, b) {
 return a + b
}

const res = sum(10, 20)
console.log(res) // 30
  • 以下的sum函數(shù)雖然對于固定的輸入也會返回固定的輸出,但是函數(shù)內(nèi)部修改了全局變量message,就認定為產(chǎn)生了副作用,不屬于純函數(shù)。
let message = 'hello'
function sum(a, b) {
 message = 'hi'
 return a + b
}
  • 在JavaScript中也提供了許多的內(nèi)置方法,有些是純函數(shù),有些則不是。像操作數(shù)組的兩個方法slice和splice。

1.slice方法就是一個純函數(shù),因為對于同一個數(shù)組固定的輸入可以得到固定的輸出,且沒有任何副作用;

const nums = [1, 2, 3, 4, 5]
const newNums = nums.slice(1, 3)
console.log(newNums) // [2, 3]
console.log(nums) // [ 1, 2, 3, 4, 5 ]

2.splice方法不是一個純函數(shù),因為它改變了原數(shù)組nums;

const nums = [1, 2, 3, 4, 5]
const newNums = nums.splice(1, 3)
console.log(newNums) // [ 2, 3, 4 ]
console.log(nums) // [ 1, 5 ]

柯里化

柯里化的概念

對于柯里化的定義,維基百科中是這樣解釋的:

  • 柯里化是指把接收多個參數(shù)的函數(shù),變成接收一個單一參數(shù)(最初函數(shù)的第一個參數(shù))的函數(shù),并且返回接收余下的參數(shù),而且返回結(jié)果的新函數(shù)的技術(shù);
  • 柯里化聲稱**“如果你固定某些參數(shù),你將得到接受余下參數(shù)的一個函數(shù)”**;

總結(jié):只傳遞給函數(shù)一部分參數(shù)來調(diào)用它,讓它返回一個函數(shù)去處理剩余的參數(shù)的過程就稱之為柯里化。

函數(shù)柯里化的過程

編寫一個普通的三值求和函數(shù):

function sum(x, y, z) {
 return x + y + z
}
const res = sum(10, 20, 30)
console.log(res) // 60

將以上求和函數(shù)柯里化得:

  • 將傳入的三個參數(shù)進行拆解,依次返回一個函數(shù),并傳入一個參數(shù);
  • 在保證同樣功能的同時,其調(diào)用方式卻發(fā)生了變化;
  • 注意:在拆解參數(shù)時,不一定非要將參數(shù)拆成一個個的,也可以拆成2+1或1+2;
function sum(x) {
 return function(y) {
 return function(z) {
 return x + y + z
 }
 }
}
const res = sum(10)(20)(30)
console.log(res)

使用ES6箭頭函數(shù)簡寫為:

const sum = x => y => z => x + y + z

函數(shù)柯里化的特點及應(yīng)用

  • **讓函數(shù)的職責(zé)更加單一。**柯里化可以實現(xiàn)讓一個函數(shù)處理的問題盡可能的單一,而不是將一大堆邏輯交給一個函數(shù)來處理。

1.將上面的三值求和函數(shù)增加一個需求,在計算結(jié)果之前給每個值加上2,先看看不使用柯里化的實現(xiàn)效果:

function sum(x, y, z) {
 x = x + 2
 y = y + 2
 z = z + 2
 return x + y + z
}

2.柯里化的實現(xiàn)效果:

function sum(x) {
 x = x + 2
 return function(y) {
 y = y + 2
 return function(z) {
 z = z + 2
 return x + y + z
 }
 }
}

3.很明顯函數(shù)柯里化后,讓我們對每個參數(shù)的處理更加單一

  • **提高函數(shù)參數(shù)邏輯復(fù)用。**同樣使用上面的求和函數(shù),增加另一個需求,固定第一個參數(shù)的值為10,直接看柯里化的實現(xiàn)效果吧,后續(xù)函數(shù)調(diào)用時第一個參數(shù)值都為10的話,就可以直接調(diào)用sum10函數(shù)了。
function sum(x) {
 return function(y) {
 return function(z) {
 return x + y + z
 }
 }
}
const sum10 = sum(10) // 指定第一個參數(shù)值為10的函數(shù)
const res = sum10(20)(30)
console.log(res) // 60

自動柯里化函數(shù)的實現(xiàn)

function autoCurrying(fn) {
 // 1.拿到當前需要柯里化函數(shù)的參數(shù)個數(shù)
 const fnLen = fn.length

 // 2.定義一個柯里化之后的函數(shù)
 function curried\_1(...args1) {
 // 2.1拿到當前傳入?yún)?shù)的個數(shù)
 const argsLen = args1.length

 // 2.1.將當前傳入?yún)?shù)個數(shù)和fn需要的參數(shù)個數(shù)進行比較
 if (argsLen >= fnLen) {
 // 如果當前傳入的參數(shù)個數(shù)已經(jīng)大于等于fn需要的參數(shù)個數(shù)
 // 直接執(zhí)行fn,并在執(zhí)行時綁定this,并將對應(yīng)的參數(shù)數(shù)組傳入
 return fn.apply(this, args1)
 } else {
 // 如果傳入的參數(shù)不夠,說明需要繼續(xù)返回函數(shù)來接收參數(shù)
 function curried\_2(...args2) {
 // 將參數(shù)進行合并,遞歸調(diào)用curried\_1,直到參數(shù)達到fn需要的參數(shù)個數(shù)
 return curried\_1.apply(this, [...args1, ...args2])
 }

 // 返回繼續(xù)接收參數(shù)函數(shù)
 return curried\_2
 }
 }

 // 3.將柯里化的函數(shù)返回
 return curried\_1
}

測試:

function sum(x, y, z) {
 return x + y + z
}

const curryingSum = autoCurrying(sum)

const res1 = curryingSum(10)(20)(30)
const res2 = curryingSum(10, 20)(30)
const res3 = curryingSum(10)(20, 30)
const res4 = curryingSum(10, 20, 30)
console.log(res1) // 60
console.log(res2) // 60
console.log(res3) // 60
console.log(res4) // 60

組合函數(shù)

**組合函數(shù)(Compose Function)**是在JavaScript開發(fā)過程中一種對函數(shù)的使用技巧、模式。對某一個數(shù)據(jù)進行函數(shù)調(diào)用,執(zhí)行兩個函數(shù),這兩個函數(shù)需要依次執(zhí)行,所以需要將這兩個函數(shù)組合起來,自動依次調(diào)用,而這個過程就叫做函數(shù)的組合,組合形成的函數(shù)就叫做組合函數(shù)。

需求:對一個數(shù)字先進行乘法運算,再進行平方運算。

  • 一般情況下,需要先定義兩個函數(shù),然后再對其依次調(diào)用:
function double(num) {
 return num * 2
}
function square(num) {
 return num ** 2
}
const duobleResult = double(10)
const squareResult = square(duobleResult)
console.log(squareResult) // 400

實現(xiàn)一個組合函數(shù),將duoble和square兩個函數(shù)組合起來:

function composeFn(fn1, fn2) {
 return function(num) {
 return fn2(fn1(num))
 }
}
const execFn = composeFn(double, square)
const res = execFn(10)
console.log(res) // 400

實現(xiàn)一個自動組合函數(shù)的函數(shù):

function autoComposeFn(...fns) {
 // 1.拿到需要組合的函數(shù)個數(shù)
 const fnsLen = fns.length

 // 2.對傳入的函數(shù)進行邊界判斷,所有參數(shù)必須為函數(shù)
 for (let i = 0; i < fnsLen; i++) {
 if (typeof fns[i] !== 'function') {
 throw TypeError('The argument passed must be a function.')
 }
 }

 // 3.定義一個組合之后的函數(shù)
 function composeFn(...args) {
 // 3.1.拿到第一個函數(shù)的返回值
 let result = fns[0].apply(this, args)

 // 3.1.判斷傳入的函數(shù)個數(shù)
 if (fnsLen === 1) {
 // 如果傳入的函數(shù)個數(shù)為一個,直接將結(jié)果返回
 return result
 } else {
 // 如果傳入的函數(shù)個數(shù) >= 2
 // 依次將函數(shù)取出進行調(diào)用,將上一個函數(shù)的返回值作為參數(shù)傳給下一個函數(shù)
 // 從第二個函數(shù)開始遍歷
 for (let i = 1; i < fnsLen; i++) {
 result = fns[i].call(this, result)
 }

 // 將結(jié)果返回
 return result
 }
 }

 // 4.將組合之后的函數(shù)返回
 return composeFn
}

測試:

function double(num) {
 return num * 2
}
function square(num) {
 return num ** 2 
}

const composeFn = autoComposeFn(double, square)
const res = composeFn(10)
console.log(res) // 400

到此這篇關(guān)于JS函數(shù)式編程之純函數(shù)、柯里化以及組合函數(shù)的文章就介紹到這了,更多相關(guān)純函數(shù)、柯里化、組合函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

樟树市| 湖北省| 滨州市| 长乐市| 阜城县| 昆明市| 武宣县| 明光市| 承德县| 桐庐县| 苍溪县| 石门县| 涞源县| 区。| 静乐县| 紫阳县| 永清县| 冕宁县| 呼和浩特市| 武宣县| 宜宾市| 哈巴河县| 长沙市| 永寿县| 武定县| 山阴县| 大连市| 突泉县| 海阳市| 三明市| 鄂托克前旗| 天台县| 平度市| 林西县| 长武县| 德庆县| 甘洛县| 庆城县| 洛浦县| 连山| 磴口县|