理解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 相关文章推荐
js网页版计算器的简单实现
Jul 02 Javascript
JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)
Aug 16 Javascript
jquery操作HTML5 的data-*的用法实例分享
Aug 17 Javascript
JavaScript实现动态创建CSS样式规则方案
Sep 06 Javascript
bootstrap改变按钮加载状态
Dec 01 Javascript
jQuery实现可用于博客的动态滑动菜单
Mar 09 Javascript
Javascript实现图片轮播效果(二)图片序列节点的控制实现
Feb 17 Javascript
JS实现表单多文件上传样式美化支持选中文件后删除相关项
Sep 30 Javascript
JavaScript中的 attribute 和 jQuery中的 attr 方法浅析
Jan 04 Javascript
js 简易版滚动条实例(适用于移动端H5开发)
Jun 26 Javascript
原生JS实现轮播图效果
Oct 12 Javascript
原生JS检测CSS3动画是否结束的方法详解
Jan 27 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
php指定函数参数默认值示例代码
2013/12/04 PHP
php生成QRcode实例
2014/09/22 PHP
PHP、Java des加密解密实例
2015/04/27 PHP
PHP实现的基于单向链表解决约瑟夫环问题示例
2017/09/30 PHP
javascript重复绑定事件造成的后果说明
2013/03/02 Javascript
解析offsetHeight,clientHeight,scrollHeight之间的区别
2013/11/20 Javascript
node+express+ejs制作简单页面上手指南
2014/11/26 Javascript
jquery实现隐藏在左侧的弹性弹出菜单效果
2015/09/18 Javascript
Angularjs material 实现搜索框功能
2016/03/08 Javascript
jQuery自制提示框tooltip改进版
2016/08/01 Javascript
微信小程序 时间格式化(util.formatTime(new Date))详解
2016/11/16 Javascript
JAVA中截取字符串substring用法详解
2017/04/14 Javascript
使用ES6语法重构React代码详解
2017/05/09 Javascript
node基于puppeteer模拟登录抓取页面的实现
2018/05/09 Javascript
vue.js提交按钮时进行简单的if判断表达式详解
2018/08/08 Javascript
vue完成项目后,打包成静态文件的方法
2018/09/03 Javascript
Vue自定义组件双向绑定实现原理及方法详解
2020/09/03 Javascript
vue 修改 data 数据问题并实时显示操作
2020/09/07 Javascript
详解Vite的新体验
2021/02/22 Javascript
python实现合并两个数组的方法
2015/05/16 Python
wx.CheckBox创建复选框控件并响应鼠标点击事件
2018/04/25 Python
浅谈Python的条件判断语句if/else语句
2019/03/21 Python
jupyter lab文件导出/下载方式
2020/04/22 Python
使用css3背景渐变中的透明度来设置不同颜色的背景渐变
2014/03/31 HTML / CSS
关于h5中的fetch方法解读(小结)
2017/11/15 HTML / CSS
英国天然保健品网站:Simply Supplements
2017/03/22 全球购物
美国基督教约会网站:ChristianCafe.com
2020/02/04 全球购物
路政管理毕业自荐书范文
2014/02/10 职场文书
文明风采获奖感言
2014/02/18 职场文书
小学英语教师先进事迹
2014/05/28 职场文书
出差报告范文
2014/11/06 职场文书
民事和解协议书格式
2014/11/29 职场文书
品质保证书格式
2015/02/28 职场文书
2015年工商所工作总结
2015/05/21 职场文书
2016年暑假学生家长评语
2015/12/01 职场文书
会计继续教育培训心得体会
2016/01/19 职场文书