目录
性能:一个警告
使用Map方法
什么是函子?
使用Reduce方法
结论
首页 web前端 js教程 如何在JavaScript函数式编程里使用Map和Reduce方法的详解

如何在JavaScript函数式编程里使用Map和Reduce方法的详解

Mar 08, 2017 pm 02:53 PM

所有人都谈论道workflows支持ECMAScript6里出现的令人吃惊的新特性,因此我们很容易忘掉ECMAScript5带给我们一些很棒的工具方法来支持在JavaScript里进行函数编程,这些工具方法我们现在可以使用了。在这些函数方法里主要的是基于JavaScript 数组对象的map()方法和reduce()方法。

如果你如今还没有使用map()和reduce()方法,那么现在是时候开始使用了。如今绝大部分的JavaScript开发平台都与生俱来的支持ECMAScript5。使用Map方法和reduce方法可以使你的代码更加简洁和更容易阅读和更容易维护,而且把你带到朝向更简洁的功能开发的路上。

性能:一个警告

当然,当现实状况需要保持提高性能时,你的代码的易读性和易维护性不得不在两者之间保持平衡。如今的浏览器使用更笨重的传统技术例如for循环来执行的更有效率。

我写代码的方式通常是把可读性和可维护性放在编写代码的第一位,然后如果我发现在现实情况里代码运行出现了问题,再去为了提高性能而去优化代码。过早的优化代码是很困难的,而且这种优化会导致后面编写代码很困难。

值得考虑的是在JavaScript引擎里使用诸如map()和reduce()这样的方法可以更好地改善代码的性能,而不是指望将来浏览器能为了改善性能而做出优化。除非我在一个性能问题上碰壁,要不然我更喜欢开心地写代码,然而以防我需要它们我却随时准备着为保持代码的性能而做出调整,尽管这样做使我的代码减少了吸引力。

使用Map方法

映射是一个基本的函数式编程技术,它对一个数组中的所有元素和创建的具有相同长度并有着转换内容的其他数组起作用。

为了使刚才的说法更加具体一点,我想出了一个简单使用示例。例如,想象一下你有一个数组,数组里有字符数据,而且你需要把它们转换进另一个数组,这个数组里包含每一个字符数据的长度。(我知道,那没有复杂到火箭科学那种程度,这是你编写复杂的应用经常不得不去做的事情,但是理解它在一个简单示例例如这个里的工作原理将有助于你使用它,在这种情况下,你可以在你的代码里给它添加真实的数据值)。

你也许知道刚才我描述的在一个数组上使用for循环如何做。它可能看起来像这样:

var animals = ["cat","dog","fish"];
var lengths = [];
var item;
var count;
var loops = animals.length;
for (count = 0; count < loops; count++){
  item = animals[count];
  lengths.push(item.length);
}
console.log(lengths); //[3, 3, 4]
登录后复制

所有我们需要做的事情是定义少量的变量:一个命名为animals的数组包含了我们需要的字符数据,一个命名为lengths的空数组将来用来包含我们操作数组数据输出的长度,和一个叫做item的变量,这个变量用来临时存储每一次循环遍历该数组时我们需要操作的数组项。我们定义了一个for循环,这个for循环有个内部变量和一个循环变量来初始化我们的for循环。然后我们循环迭代每一个项,直到迭代的数组长度等于animals数组的长度。每一次循环我们都计算迭代项的字符长度,然后把它保存到lengths数组里。

注意:需要讨论的是我们可以把上面的代码写得更简洁些,不需要那个item变量,而直接把animals[count]的长度放到lengths数组里,这样就不需要中间的转换过程了。这样做可以帮我们省一点点代码空间,但是它也使得我们的代码有点不易阅读,即使是这个很简单的例子也一样。相同地,为了使代码更有效率而少些直白,我们可能会使用已知的animals数组长度来通过new Array(animals.length)的方式来初始化我们的lengths数组,然后通过索引而不是使用push方法来插入选项数据长度。这取决于你在现实中准备如何去使用这些代码。

这种实现方式没有任何的技术错误。它在任何标准的JavaScript引擎里都可以用,并且它能很好的完成工作。一旦你知道怎么使用map()方法了,通过这种方法来实现就显得有些笨拙了。

让我展示给你看使用map()方法是如何实现上面的代码的:

var animals = ["cat","dog","fish"];
var lengths = animals.map(function(animal) {
  return animal.length;
});
console.log(lengths); //[3, 3, 4]
登录后复制

在这个小例子里,我们首先再次为我们的animal类型的数组创建一个animals变量。然而,其他我们需要声明的变量就是lengths变量了,然后我们直接分配它的值到映射一个匿名内联函数到animals数组的每一个元素上的结果中。

那个匿名函数执行在每一个animal 上的的操作,然后返回该animal的字符长度。这样做的结果是,lengths变成了具有与原始animals数组有相同长度的数组,并且该数组包含了每一个字符的长度。

这种方式需要注意的一些事情。首先,它比最初编写的代码更简洁。其次,我们仅需要申明更少的变量。更少的变量意味着在全局命名空间里杂音更少,并且如果相同代码的其他部分使用了相同的变量名就会减少碰撞的机会。最后,我们的变量不可能从头到脚都会改变它们的值。随着你深入函数式编程,你将会欣赏使用常量和不变的变量的优雅的能力,现在开始使用并不算早。

这种实现方式的另一个优点是,我们可以通过在整个代码编写过程中通过将代码放进一个个命名的函数里而简化代码而有机会提升自己编写代码的多功能性。匿名的内联函数看着有些乱,并且使得重复使用代码更困难。我们可以定义一个命名为getLength()的函数,并且像下面的方式来使用:

var animals = ["cat","dog","fish"];
function getLength(word) {
  return word.length;
}
console.log(animals.map(getLength)); //[3, 3, 4]
登录后复制

看看上面的代码看上去多简洁啊?只是把你处理数据的部分映射一下就使你的代码达到一个全新的功能水平。

什么是函子?

有趣的一点是,通过在数组对象里添加映射,ECMAScript5把基本的数组类型变成了一个完整的函子,这使得函数式编程对我们来说更加的容易。

根据传统的函数编程定义,一个函子需要满足三个条件:

  • 1.它保存着一组值。

  • 2.它实现了一个map函数来操作每一个元素。

  • 3.它的map函数返回一个具有同样大小的函子。

这个将会在你下一次的JavaScript聚会上被翻来覆去的讨论。

如果你想了解更多关于函子的信息,你可以看看Mattias Petter Johansson录制的关于这方面的视频。

使用Reduce方法

Reduce()方法在ECMAScript5里也是新增的,而且它和map()方法很类似,除了不产生其他的函子,reduce()方法产生的一个结果是它可能是任何类型。例如,设想一下,如果你想得到我们animals数组里的所有字符长度都分别作为一个数字然后相加的结果。你也许会像下面这样做:

var animals = ["cat","dog","fish"];
var total = 0;
var item;
for (var count = 0, loops = animals.length; count < loops; count++){
  item = animals[count];
  total += item.length;
}
console.log(total); //10
登录后复制

在我们定义我们的初始数组之后,我们为运行总计定义了一个total变量,并把它的初始值设为0。我们也定义一个变量item来保存每一次for循环迭代animals数组的迭代值,并且再定义一个count变量作为一个循环计数器,并且用这两个变量来初始化我们的迭代。然后我们运行for循环来迭代animals数组里的所有字符数据,每次迭代都会把迭代的结果保存到item变量。最终我们把每一次迭代到的item的长度加到我们的total变量里就可以了。

这种实现方式也没有任何的技术错误。我们从定义一个数组开始,然后得到一个结果值就结束了。但是如果我们使用了reduce()方法,我们可以使上面的代码更加简单明了:

var animals = ["cat","dog","fish"];
var total = animals.reduce(function(sum, word) {
  return sum + word.length;
}, 0);
console.log(total);
登录后复制

这里发生变化的是,我们定义了一个名为total的新变量,并且把执行animals数组对象的reduce方法的返回值分配给它,在reduce方法里有两个参数:一个匿名内联function方法,和初始化total的值为0。对于数组中的每一个项reduce()方法都会执行,它在数组的那一项上执行这个function函数,并且把它添加到运行总计,然后再进行下一次迭代。这里我们的内联function方法有两个参数:运行总计,和当前程序正在处理的从数组中获取的字符。这个function函数把当前total的值添加到当前word的长度上。

注意的是:我们设置reduce()方法的第二个参数值为0,这样做确定了total变量包含的是一个数值。如果没有第二个参数reduce方法仍然可以执行,但是执行的结果将不是你期望的那样。(你可以试试并且可以看看当运行总计结束后你是否能推测出JavaScript所使用的编程逻辑。)

那看上去似乎比它需要做的更有一点复杂,因为当调用reduce()方法时需要在一个内联function里综合的定义。我们再那么做一次,但是首先让我们定义一个命名的function函数,而不再使用匿名内联函数:

var animals = ["cat","dog","fish"];
var addLength = function(sum, word) {
  return sum + word.length;
};
var total = animals.reduce(addLength, 0);
console.log(total);
登录后复制

这个代码稍微有点长,但是代码有点长并不总是坏事。这样写你应该看到它使代码更加清晰些,只是在reduce()方法里发生了一点变化。

该程序里reduce()方法有两个参数:一个function函数,用来调用数组里的每一个元素,和一个为total变量设置的运行总计初始值。在这个代码示例中,我们放入了一个名为addLength的新function和为运行总计变量赋初始值为0。在上一行代码中,我们定义了一个名为addLength的function函数,这个函数也需要两个参数:一个当前和一个要处理的字符串。

结论

经常使用map()方法和reduce()方法将会为你的代码更加简洁,更加多功能,更加可维护性提供了选择。同时它们为你使用更多的JavaScript功能函数技术铺平了道路。

map()方法和reduce()方法仅是被添加进ECMAScript5中新方法中的两个。从使用它们的今天你将会明白代码质量的提高和开发人员满意度的提升胜过任何在性能上的临时影响。在判断map()方法和reduce()方法是否适合你的应用之前,试着用功能函数技术来开发和度量一下它在你现实世界里的影响,然后再判断是否去用。


以上是如何在JavaScript函数式编程里使用Map和Reduce方法的详解的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何使用WebSocket和JavaScript实现在线语音识别系统 如何使用WebSocket和JavaScript实现在线语音识别系统 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript实现在线语音识别系统引言:随着科技的不断发展,语音识别技术已经成为了人工智能领域的重要组成部分。而基于WebSocket和JavaScript实现的在线语音识别系统,具备了低延迟、实时性和跨平台的特点,成为了一种被广泛应用的解决方案。本文将介绍如何使用WebSocket和JavaScript来实现在线语音识别系

WebSocket与JavaScript:实现实时监控系统的关键技术 WebSocket与JavaScript:实现实时监控系统的关键技术 Dec 17, 2023 pm 05:30 PM

WebSocket与JavaScript:实现实时监控系统的关键技术引言:随着互联网技术的快速发展,实时监控系统在各个领域中得到了广泛的应用。而实现实时监控的关键技术之一就是WebSocket与JavaScript的结合使用。本文将介绍WebSocket与JavaScript在实时监控系统中的应用,并给出代码示例,详细解释其实现原理。一、WebSocket技

如何利用JavaScript和WebSocket实现实时在线点餐系统 如何利用JavaScript和WebSocket实现实时在线点餐系统 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket实现实时在线点餐系统介绍:随着互联网的普及和技术的进步,越来越多的餐厅开始提供在线点餐服务。为了实现实时在线点餐系统,我们可以利用JavaScript和WebSocket技术。WebSocket是一种基于TCP协议的全双工通信协议,可以实现客户端与服务器的实时双向通信。在实时在线点餐系统中,当用户选择菜品并下单

如何使用WebSocket和JavaScript实现在线预约系统 如何使用WebSocket和JavaScript实现在线预约系统 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript实现在线预约系统在当今数字化的时代,越来越多的业务和服务都需要提供在线预约功能。而实现一个高效、实时的在线预约系统是至关重要的。本文将介绍如何使用WebSocket和JavaScript来实现一个在线预约系统,并提供具体的代码示例。一、什么是WebSocketWebSocket是一种在单个TCP连接上进行全双工

JavaScript和WebSocket:打造高效的实时天气预报系统 JavaScript和WebSocket:打造高效的实时天气预报系统 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的实时天气预报系统引言:如今,天气预报的准确性对于日常生活以及决策制定具有重要意义。随着技术的发展,我们可以通过实时获取天气数据来提供更准确可靠的天气预报。在本文中,我们将学习如何使用JavaScript和WebSocket技术,来构建一个高效的实时天气预报系统。本文将通过具体的代码示例来展示实现的过程。We

优化Go语言map的性能 优化Go语言map的性能 Mar 23, 2024 pm 12:06 PM

优化Go语言map的性能在Go语言中,map是一种非常常用的数据结构,用来存储键值对的集合。然而,在处理大量数据时,map的性能可能受到影响。为了提高map的性能,我们可以采取一些优化措施来减少map操作的时间复杂度,从而提升程序的执行效率。1.预分配map的容量在创建map时,我们可以通过预分配容量来减少map扩容的次数,提高程序的性能。一般情况下,我们

简易JavaScript教程:获取HTTP状态码的方法 简易JavaScript教程:获取HTTP状态码的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教程:如何获取HTTP状态码,需要具体代码示例前言:在Web开发中,经常会涉及到与服务器进行数据交互的场景。在与服务器进行通信时,我们经常需要获取返回的HTTP状态码来判断操作是否成功,根据不同的状态码来进行相应的处理。本篇文章将教你如何使用JavaScript获取HTTP状态码,并提供一些实用的代码示例。使用XMLHttpRequest

JavaScript和WebSocket:打造高效的实时图像处理系统 JavaScript和WebSocket:打造高效的实时图像处理系统 Dec 17, 2023 am 08:41 AM

JavaScript是一种广泛应用于Web开发的编程语言,而WebSocket则是一种用于实时通信的网络协议。结合二者的强大功能,我们可以打造一个高效的实时图像处理系统。本文将介绍如何利用JavaScript和WebSocket来实现这个系统,并提供具体的代码示例。首先,我们需要明确实时图像处理系统的需求和目标。假设我们有一个摄像头设备,可以采集实时的图像数

See all articles