JavaScript
是一種很受歡迎的編程語(yǔ)言,今天整理這篇文章是為了讓大家更深入了解一下JavaScript
。下面我將展示一些有關(guān)如何在JavaScript中應(yīng)用函數(shù)式編程的例子。
JavaScript中的函數(shù)式編程
即使函數(shù)式編程可以極大地改善應(yīng)用程序的代碼,但其原理在開始時(shí)可能會(huì)有些挑戰(zhàn)。由于詳細(xì)解釋所有這些都將花費(fèi)大量時(shí)間,因此我們決定使用兩個(gè)實(shí)際的代碼示例來介紹這些概念。
1.Maybe Monad
在第一個(gè)示例中,我們找到一種避免驗(yàn)證變量是否為Null
的方法。假設(shè)在我們的應(yīng)用程序中,我們可以找到具有以下格式的用戶:
const someUser = {
name: 'some_name',
email: 'some@email.com',
settings: {
language: 'sp'
}
};
有一個(gè)功能,可以以用戶設(shè)置的語(yǔ)言返回歡迎消息。
const allGreetings = {
'en': '嗨',
'sp': '你好',
'fr': '歡迎你'
};
const getGreetingForUser = (user) => {
//將要執(zhí)行
}
來看一個(gè)遵循命令式模型的“getGreetingForUser
”函數(shù)的實(shí)現(xiàn):
const getGreetingForUser = (user) => {
if (!user) {
return allGreetings.en;
}
if (user.settings && user.settings.language) {
if (allGreetings[user.settings.language]) {
return allGreetings[user.settings.language]
} else {
return allGreetings.en;
}
} else {
return allGreetings.en;
}
};
console.log(getGreetingForUser(someUser));
如上面所看到的,必須檢查用戶是否已經(jīng)存在,是否已設(shè)置語(yǔ)言,以及是否已準(zhǔn)備好歡迎消息。如果出現(xiàn)問題,我們將以默認(rèn)語(yǔ)言返回一條消息。
現(xiàn)在,讓我們看一下相同的函數(shù),但是這次我們將在其實(shí)現(xiàn)中使用函數(shù)式編程:
const getGreetingForUser = (user) => {
return RamdaFantasy.Maybe(user)
.map(Ramda.path(['settings', 'language']))
.chain(maybeGreeting);
};
const maybeGreeting = Ramda.curry((greetingsList, userLanguage) => {
return RamdaFantasy.Maybe(greetingsList[userLanguage]);
})(allGreetings);
console.log(getGreetingForUser(someUser).getOrElse(allGreetings.en));
為了處理可能為null
或未定義的情況,我們將使用Maybe Monad
。這使我們可以在對(duì)象周圍創(chuàng)建包裝器,并為空對(duì)象分配默認(rèn)行為。
讓我們比較兩種解決方案:
//代替驗(yàn)證用戶是否為空
if (!user) {
return allGreetings.en;
}
//我們將用:
RamdaFantasy.Maybe(user) //我們將用戶添加到包裝器中
//代替:
if (user.settings && user.settings.language) {
if (allGreetings[user.settings.language]) {
//我們將用:
<userMaybe>.map(Ramda.path(['settings', 'language'])) //如果存在數(shù)據(jù),映射將會(huì)用它
//不是在else中返回默認(rèn)值:
return indexURLs['en'];
.getOrElse(allGreetings。EN)
// 指定的默認(rèn)值。
2 Either Monad
當(dāng)我們知道存在空錯(cuò)誤時(shí)的默認(rèn)行為時(shí),Maybe Monad
非常有用。
但是,如果我們有一個(gè)引發(fā)錯(cuò)誤的函數(shù),或者我們將各種引發(fā)錯(cuò)誤的函數(shù)鏈接在一起,并且我們想知道哪個(gè)發(fā)生了故障,則可以改用Either Monad
。
現(xiàn)在,讓我們假設(shè)我們要計(jì)算產(chǎn)品的價(jià)格,同時(shí)考慮增值稅和可能的折扣。我們已經(jīng)有了以下代碼:
const withTaxes = (tax, price) => {
if (!_.isNumber(price)) {
return new Error("Price is not numeric");
}
return price + (tax * price);
};
const withDiscount = (dis, price) => {
if (!_.isNumber(price)) {
return new Error("Price is not numeric");
}
if (price < 5)
return new Error("Discounts not available for low-priced items");
}
return price - (price * dis);5
};
const isError = (e) => e && e.name === 'Error';
const calculatePrice(price, tax, discount) => {
//將要執(zhí)行
}
讓我們來看一個(gè)遵循命令式模型的“calculatePrice
”函數(shù)的實(shí)現(xiàn):
const calculatePrice = (price, tax, discount) => {
const priceWithTaxes = withTaxes(tax, price);
if (isError(priceWithTaxes)) {
return console.log('Error: ' + priceWithTaxes.message);
}
const priceWithTaxesAndDiscount = withDiscount(discount, priceWithTaxes);
if (isError(priceWithTaxesAndDiscount)) {
return console.log('Error: ' + priceWithTaxesAndDiscount.message);
}
console.log('Total Price: ' + priceWithTaxesAndDiscount);
}
//我們計(jì)算出價(jià)值25的產(chǎn)品(含21%的增值稅和10%的折扣)的最終價(jià)格。
calculatePrice(25, 0.21, 0.10)
現(xiàn)在,讓我們了解如何使用Either Monad
重寫此函數(shù)。
都有兩個(gè)構(gòu)造函數(shù),Left
和Right
。我們要實(shí)現(xiàn)的是將異常存儲(chǔ)到Left
構(gòu)造函數(shù),并將正常結(jié)果(快樂路徑)存儲(chǔ)到Right
構(gòu)造函數(shù)。
首先,將更改已經(jīng)存在的withTaxes
和withDiscount
函數(shù),以便在出現(xiàn)錯(cuò)誤時(shí)它們返回Left
,在一切正常的情況下返回Right
:
const withTaxes = Ramda.curry((tax, price) => {
if (!_.isNumber(price)) {
return RamdaFantasy.Either.Left(new Error("Price is not numeric"));
}
return RamdaFantasy.Either.Right(price + (tax * price));
});
const withDiscount = Ramda.curry((dis, price) => {
if (!_.isNumber(price)) {
return RamdaFantasy.Either.Left(new Error("Price is not numeric"));
}
if (price < 5) {
return RamdaFantasy.Either.Left(new Error("Discounts not available for low-priced items"));
}
return RamdaFantasy.Either.Right(price - (price * dis));
});
然后,我們?yōu)?code>Right案例創(chuàng)建一個(gè)函數(shù)(顯示價(jià)格),為Left
案例創(chuàng)建另一個(gè)函數(shù)(顯示錯(cuò)誤),然后使用它們創(chuàng)建Either Monad
:
const showPrice = (total) => { console.log('Price: ' + total) };
const showError = (error) => { console.log('Error: ' + error.message); };
const eitherErrorOrPrice = RamdaFantasy.Either.either(showError, showPrice);
最后,只需要執(zhí)行Monad來計(jì)算最終價(jià)格:
//計(jì)算出價(jià)值25的產(chǎn)品(含21%的增值稅和10%的折扣)的最終價(jià)格。
eitherErrorOrPrice(
RamdaFantasy.Either.Right(25)
.chain(withTaxes(0.21))
.chain(withDiscount(0.1))
)
結(jié)論:JavaScript中的函數(shù)式編程
正如我們所看到的,一旦用Maybe
和Either
單子分解了代碼,就沒有那么復(fù)雜了。如果使用得當(dāng),它們可以使我們的代碼更易于閱讀和維護(hù)。
唯一的不便是我們需要克服的初始障礙,但這可以通過在網(wǎng)上一些示例并進(jìn)行一些測(cè)試來完成。
以上就是JavaScript
中應(yīng)用函數(shù)式編程的示例,希望能對(duì)大家有所幫助。然后想學(xué)習(xí)JavaScript
的同學(xué)可以點(diǎn)以下鏈接
JavaScript教程:http://m.hgci.cn/javascript/
JavaScript微課:http://m.hgci.cn/minicourse/play/jscourse
文章參考來源:www.toutiao.com/a6836176173207126541/