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