您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

JavaScript中的函数式编程

时间:2020-06-09 14:06:56  来源:  作者:

JAVAScript是一种发展迅速的语言。这篇文章,我想展示一些有关如何在JavaScript中应用函数式编程的示例。

JavaScript中的函数式编程

即使函数式编程可以极大地改善应用程序的代码,但其原理在开始时可能会有些挑战。由于详细解释所有这些都将花费大量时间,因此我们决定使用两个实际的代码示例来介绍这些概念

解析:JavaScript中的函数式编程

 

1.Maybe Monad

在第一个示例中,我们找到一种避免验证变量是否为Null的方法。假设在我们的应用程序中,我们可以找到具有以下格式的用户:

const someUser = {
 name: 'some_name',
 email: 'some@email.com',
 settings: {
  language: 'sp'
 }
};

有一个功能,可以以用户设置的语言返回欢迎消息。

const allGreetings = {
 'en': '嗨',
 'sp': '你好',
 'fr': '欢迎你'
};
const getGreetingForUser = (user) => {
 //将要执行
}

来看一个遵循命令式模型的“ getGreetingForUser”函​​数的实现:

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));

如上面所看到的,必须检查用户是否已经存在,是否已设置语言,以及是否已准备好欢迎消息。如果出现问题,我们将以默认语言返回一条消息。

现在,让我们看一下相同的函数,但是这次我们将在其实现中使用函数式编程:

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。这使我们可以在对象周围创建包装器,并为空对象分配默认行为。

解析:JavaScript中的函数式编程

 

让我们比较两种解决方案:

//代替验证用户是否为空
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'])) //如果存在数据,映射将会用它
//不是在else中返回默认值:
 return indexURLs['en'];
.getOrElse(allGreetings。EN)
// 指定的默认值。

2 Either Monad

当我们知道存在空错误时的默认行为时,Maybe Monad非常有用。

但是,如果我们有一个引发错误的函数,或者我们将各种引发错误的函数链接在一起,并且我们想知道哪个发生了故障,则可以改用Either Monad。

解析:JavaScript中的函数式编程

 

现在,让我们假设我们要计算产品的价格,同时考虑增值税和可能的折扣。我们已经有了以下代码:

const withTaxes = (tax, price) => {
2
 if (!_.isNumber(price)) {
3
 return new Error("Price is not numeric");
4
 }
5
 return price + (tax * price);
6
};
7
const withDiscount = (dis, price) => { 
8
  if (!_.isNumber(price)) { 
9
    return new Error("Price is not numeric"); 
10
  } 
11
  if (price < 5) 
12
    return new Error("Discounts not available for low-priced items"); 
13
  } 
14
  return price - (price * dis);5
}; 
const isError = (e) => e && e.name === 'Error';
const calculatePrice(price, tax, discount) => { 
//将要执行
}

让我们来看一个遵循命令式模型的“ calculatePrice”函数的实现:

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的产品(含21%的增值税和10%的折扣)的最终价格。
 calculatePrice(25, 0.21, 0.10)

现在,让我们了解如何使用Either Monad重写此函数。

都有两个构造函数,Left和Right。我们要实现的是将异常存储到Left构造函数,并将正常结果(快乐路径)存储到Right构造函数。

首先,将更改已经存在的withTaxes和withDiscount函数,以便在出现错误时它们返回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)); 
});


然后,我们为Right案例创建一个函数(显示价格),为Left案例创建另一个函数(显示错误),然后使用它们创建Either Monad:

const showPrice = (total) => { console.log('Price: ' + total) }; 
const showError = (error) => { console.log('Error: ' + error.message); }; 
const eitherErrorOrPrice = RamdaFantasy.Either.either(showError, showPrice);

最后,只需要执行Monad来计算最终价格:

//计算出价值25的产品(含21%的增值税和10%的折扣)的最终价格。
 eitherErrorOrPrice(
   RamdaFantasy.Either.Right(25)
     .chain(withTaxes(0.21))
     .chain(withDiscount(0.1))
)

结论:JavaScript中的函数式编程

正如我们所看到的,一旦用Maybe和Either单子分解了代码,就没有那么复杂了。如果使用得当,它们可以使我们的代码更易于阅读和维护。



Tags:JavaScript 函数式编程   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
JavaScript是一种发展迅速的语言。这篇文章,我想展示一些有关如何在JavaScript中应用函数式编程的示例。JavaScript中的函数式编程即使函数式编程可以极大地改善应用程序的代...【详细内容】
2020-06-09  Tags: JavaScript 函数式编程  点击:(57)  评论:(0)  加入收藏
函数式编程在前端已经成为了一个非常热门的话题。在最近几年里,我们看到非常多的应用程序代码库里大量使用着函数式编程思想。...【详细内容】
2019-09-24  Tags: JavaScript 函数式编程  点击:(265)  评论:(0)  加入收藏
▌简易百科推荐
<script src="http://pv.sohu.com/cityjson?ie=utf-8"></script> <script> console.log(returnCitySN["cip"]+&#39;,&#39;+returnCitySN["cname"]) </script> JS命名空间是...【详细内容】
2022-07-14  马克-1949    Tags:js   点击:(4)  评论:(0)  加入收藏
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>计时</title> </head> <body> <div style="display: flex; justify-content: center; align-item...【详细内容】
2022-07-12  马克-1949    Tags:js   点击:(8)  评论:(0)  加入收藏
今天,我们来总结下我们平常使用的工具函数,希望对大家有用。 1、封装fetch 源码: /** * 封装fetch函数,用Promise做回调 * @type {{get: (function(*=)), post: (function(*=,...【详细内容】
2022-07-07  马克-1949    Tags:JS   点击:(17)  评论:(0)  加入收藏
let arr = ["2", "4", "6", "8", "10", "12", "14", "16", "18", "20", "22", "24", "27", "30", "33", "36...【详细内容】
2022-07-06  马克-1949    Tags:js   点击:(24)  评论:(0)  加入收藏
Enums 是 Enumerations 的缩写,是预设的常量,可以由开发人员定义以在代码的其他地方使用。 对于 JavaScript 开发人员来说,枚举的概念通常是新的,但它们相对容易理解。 Enums 为...【详细内容】
2022-07-06  庄志炎    Tags:TypeScript   点击:(25)  评论:(0)  加入收藏
前言在之前实现的 JSON 解析器中当时只实现了将一个 JSON 字符串转换为一个 JSONObject,并没有将其映射为一个具体的 struct;如果想要获取值就需要先做断言将其转换为 map 或...【详细内容】
2022-07-05  crossoverJie    Tags:JSON   点击:(19)  评论:(0)  加入收藏
1、利用“或”(||)短路逻辑,给变量赋值。 // a应该是一个有意义的字符串,不能说null,undefined,nullconst getData = (a) => { // let b = ""; // if (a !== null...【详细内容】
2022-07-04  milesmatheson    Tags:Javascript   点击:(22)  评论:(0)  加入收藏
作者:极客小俊公众号同名: 一个把逻辑思维转变为代码的技术博主前言⚽你们一定在CSDN上见过以下这种强制恶心的关注 才能展开看到你想看的文章如图 好的 今天就必须教大家一...【详细内容】
2022-06-29  极客小俊    Tags:javascript   点击:(52)  评论:(0)  加入收藏
最近开发的项目上需要把数据导出为 xlsx 文档,找了一圈,发现 node-xlsx 简单好用,分享给各位。关于 node-xlsx在 web 开发中,管理后台生成 excel 报表并且下载,一个很常用的功能...【详细内容】
2022-06-24  那些免费的砖    Tags: js 库   点击:(98)  评论:(0)  加入收藏
统一资源定位符(URL),是对 Web 资源(网页、图像、文件)的引用。URL 是指定资源位置和检索资源的一种协议(如http、ftp、mailto)。如下代码,这是今日头条发布文章的URL地址:https://...【详细内容】
2022-06-24  前端石三    Tags:js   点击:(43)  评论:(0)  加入收藏
站内最新
站内热门
站内头条