理解javascript中Map代替循环


Posted in Javascript onFebruary 26, 2016

本文介绍了map给我们的js编程带来的好处及便利:
1.Map能干什么
map可以实现for循环的功能:

<!DOCTYPE html> 
<html> 
<head lang="en"> 
 <meta charset="UTF-8"> 
 <title></title> 
</head> 
<body> 
 
<script> 
 
 var arr = ['val1', 'val2', 'val3']; 
 
 for(var i = 0; i < arr.length; i++){ 
  console.log(arr[i]); 
  console.log(i); 
  console.log(arr); 
 } 
 arr.map(function(val, index, array) { 
  console.log(val); 
  console.log(index); 
  console.log(array); 
 }); 
 
  
  
 
</script> 
 
 
</body> 
</html>

这里的好处是,我们可以随意在map里面写函数,这样的话代码可读性会大大提高,如下:

function output(val, index, array) { 
  console.log(val); 
  console.log(index); 
  console.log(array); 
 } 
 
 
 arr.map(output);

2.Map的兼容性
ECMAScript 5 标准定义了原生的 map() 方法,所以浏览器兼容性较好。如果你想在 IE 9 之前的版本中使用,就需要引入一个 polyfill 或使用 Underscore、Lodash 之类的库了。
3.map和for哪个快
当然,使用for会比map快点,但是差别不是很大,如果对性能要求没有到极致的地步,这点性能差别可以忽略。

如今,在程序员学习过程中基本都会发现一个叫 map 的函数。在发现 map 函数之前,你可能都会使用 for 循环来处理需要多次执行某一行为的场景。一般情况下,在这个循环过程中都会伴随一些数据变换。

命令式

例如,你团队的销售人员交给你一个很长的电邮地址列表。这些邮箱地址获取的时候并没有经过很好地校验,以至于有些是大写的,有些是小写的,还有一些是大小写混合的。使用 for 循环进行数据处理的代码如下:

var mixedEmails = ['JOHN@ACME.COM', 'Mary@FooBar.com', 'monty@spam.eggs'];
 
function getEmailsInLowercase(emails) {
 var lowercaseEmails = [];
 
 for (var i = 0; i &lt; emails.length; i++) {
  lowercaseEmails.push(emails[i].toLowerCase());
 }
 
 return lowercaseEmails;
}
 
var validData = getEmailsInLowercase(mixedEmails);

这样的做法是有效的,但却把一个实际上简单常见的操作变得复杂。使用 for 循环的函数牵扯了很多不必要的细节。一些痛点如下:

  • 需要让程序创建一个临时列表来存储复制的邮件地址值。
  • 需要让程序先计算列表的长度,以此为次数访问一遍列表。
  • 需要让程序创建一个计数器用来记录当前访问的位置。
  • 需要告诉程序计数的方向,但顺序在这里并不重要。

这是命令式的编程方法。我们似乎在口述给电脑该怎么做这件事。

困惑

为了使之前的代码更加清晰整洁,我们改用 map 函数。在任何 map 函数的说明文档中,我们都会看到诸如 “array”、“each”、“index”之类的词。这表明,我们可以把 map 当做不那么“隆重”的 for 循环使用,事实上也是可行的。现在来修改一下之前的代码:

var mixedEmails = ['JOHN@ACME.COM', 'Mary@FooBar.com', 'monty@spam.eggs'];
 
function getEmailsInLowercase(emails) {
 var lowercaseEmails = [];
 
 emails.map(function(email) {
  lowercaseEmails.push(email.toLowerCase());
 });
 
 return lowercaseEmails;
}
 
var validData = getEmailsInLowercase(mixedEmails);

这样写不仅能用,而且代码比使用 for 循环更加清楚。除了代码量更少,我们也不用再告诉程序去记录索引和遍历列表的方向了。

然而,这还不够好。这样写还是命令式的编程。我们还是指挥的太多。实际上我们牵涉了很多不必要的细节,似乎都在领着程序的手走每一步。

声明式

我们需要改变我们关于数据变换的思考方式。我们不需要想着:“电脑啊,我需要你取出列表中第一个元素,然后把它转换成小写,再存储到另一个列表中,最后返回这个列表”。相反,我们应该这样想:“电脑,我这有一个混合了大小写的邮件地址列表,而我需要一个全是小写的邮件地址列表,这是一个能够进行小写转换的函数”。

var mixedEmails = ['JOHN@ACME.COM', 'Mary@FooBar.com', 'monty@spam.eggs'];
 
function downcase(str) {
 return str.toLowerCase();
}
 
var validData = mixedEmails.map(downcase);

毫无疑问,这种写法更易懂,同时这才是程序的本质:把你的想法告诉其他人,这个人可能是别的程序员或未来的你。上面的代码在说“有效的数据是使用小写转换函数映射后的邮箱列表”。

使用类似这样的高级方式传递想法是函数式编程的核心原则,而我们就在这样做。将单一功能、易于理解的简单部分组合起来,由此构建复杂程序。

这样的写法还有些额外的好处。下表的排序不分先后:

  • 小写转换函数提供了最简化的接口:单值输入,单值输出。
  • 能够改动的地方不多,所以逻辑更易于理解,也易于测试,而且不易出错。
  • 逻辑单一,所以易于复用,并且与其他函数能够组合出更复杂的功能。
  • 沿这样的声明式编程路线走的话,代码量会显著缩小。

虽然给 map 的第一个参数传入匿名函数很常见,还是建议把函数提出来并合理命名。这能够帮你记录下写此函数的意图,这样别的开发者就能通过函数名了解功能而不用再费劲分析代码了。

浏览器支持情况

ECMAScript 5 标准定义了原生的 map() 方法,所以浏览器兼容性较好。如果你想在 IE 9 之前的版本中使用,就需要引入一个 polyfill 或使用 Underscore、Lodash 之类的库了。

性能表现

极大多数情况下,在实际编码中 map 函数和 for 循环之间没有明显的性能差距。for 循环稍快一些,但如果你不是在写图形或物理引擎的话,这点差距没必要去考虑,当然即使如此,除非能够确定这些性能的提升对你有帮助,否则用这种方式去优化意义不大。

总结

将逻辑分成单一功能的方法并应用于数据结构上,这种编程方法会让你的代码更准确、鲁棒和易于理解。我们的理念就是尽可能通用,通用能够帮助代码重用。学习这种思考方法,不仅能帮助你提高 Javascript 水平,也能体现在其他多数编程语言上,例如 Ruby 和 Haskell。

所以,下一次当你要使用 for 循环时,重新考虑一下。记住,你要处理的数据并不一定是普通的数组,你可以去处理对象,取出它的值,再使用函数去映射,最后整理出结果数组。

以上就是关于map代替循环的简单介绍,希望对大家的学习有所帮助。

Javascript 相关文章推荐
浅谈javascript 面向对象编程
Oct 28 Javascript
js 模拟气泡屏保效果代码
Jul 10 Javascript
javascript onmouseout 解决办法
Jul 17 Javascript
js+JQuery返回顶部功能如何实现
Dec 03 Javascript
通过action传过来的值在option获取进行验证的方法
Nov 14 Javascript
JavaScript调用客户端的可执行文件(示例代码)
Nov 28 Javascript
JavaScript bold方法入门实例(把指定文字显示为粗体)
Oct 17 Javascript
网页收藏夹显示ICO图标(代码少)
Aug 04 Javascript
BootStrap中Tab页签切换实例代码
May 30 Javascript
jQuery实现的简单拖拽功能示例
Sep 13 Javascript
js中url对象化管理分析
Dec 29 Javascript
vue2.0之多页面的开发的示例
Jan 30 Javascript
JS实现随页面滚动显示/隐藏窗口固定位置元素
Feb 26 #Javascript
学习使用jquery iScroll.js移动端滚动条插件
Mar 24 #Javascript
AngularJS整合Springmvc、Spring、Mybatis搭建开发环境
Feb 25 #Javascript
JavaScript 正则表达式中global模式的特性
Feb 25 #Javascript
javascript动态获取登录时间和在线时长
Feb 25 #Javascript
基于javascript实现动态时钟效果
Aug 18 #Javascript
jQuery使用zTree插件实现树形菜单和异步加载
Feb 25 #Javascript
You might like
PHILIPS D1835/D1875的电路分析与打理
2021/03/02 无线电
JavaScript 高效运行代码分析
2010/03/18 Javascript
javascript高级程序设计第二版第十二章事件要点总结(常用的跨浏览器检测方法)
2012/08/22 Javascript
Javascript页面添加到收藏夹的简单方法
2013/08/07 Javascript
js获取客户端外网ip的简单实例
2013/11/21 Javascript
不得不分享的JavaScript常用方法函数集(上)
2015/12/23 Javascript
JavaScript判断浏览器对CSS3属性是否支持的多种方法
2016/11/13 Javascript
微信小程序开发之Tabbar实例详解
2017/01/09 Javascript
基于NodeJS+MongoDB+AngularJS+Bootstrap开发书店案例分析
2017/01/12 NodeJs
javascript 网页进度条简单实例
2017/02/22 Javascript
jQueryUI Sortable 应用Demo(分享)
2017/09/07 jQuery
关于vue-router的beforeEach无限循环的问题解决
2017/09/09 Javascript
详解vue axios用post提交的数据格式
2018/08/07 Javascript
vue-cli项目中使用echarts图表实例
2018/10/22 Javascript
vue-music 使用better-scroll遇到轮播图不能自动轮播问题
2018/12/03 Javascript
详解angular2 控制视图的封装模式
2018/12/27 Javascript
JS实现的对象去重功能示例
2019/06/04 Javascript
详解vue 自定义组件使用v-model 及探究其中原理
2019/10/11 Javascript
[37:35]DOTA2上海特级锦标赛A组资格赛#1 Secret VS MVP.Phx第二局
2016/02/25 DOTA
Python探索之爬取电商售卖信息代码示例
2017/10/27 Python
python 调用pyautogui 实时获取鼠标的位置、移动鼠标的方法
2019/08/27 Python
Python实现socket非阻塞通讯功能示例
2019/11/06 Python
python创建子类的方法分析
2019/11/28 Python
opencv3/C++实现视频读取、视频写入
2019/12/11 Python
解决pycharm上的jupyter notebook端口被占用问题
2019/12/17 Python
Python基础之函数原理与应用实例详解
2020/01/03 Python
pytorch 状态字典:state_dict使用详解
2020/01/17 Python
如何解决tensorflow恢复模型的特定值时出错
2020/02/06 Python
Python实现石头剪刀布游戏
2021/01/20 Python
CSS3使用transition实现的鼠标悬停淡入淡出
2015/01/09 HTML / CSS
利用CSS3实现的文字定时向上滚动
2016/08/29 HTML / CSS
自荐信格式写作方法有哪些呢
2013/11/20 职场文书
公务员检讨书
2014/11/01 职场文书
喋血孤城观后感
2015/06/08 职场文书
pytorch中的numel函数用法说明
2021/05/13 Python
实体类或对象序列化时,忽略为空属性的操作
2021/06/30 Java/Android