你应该了解的JavaScript Array.map()五种用途小结


Posted in Javascript onNovember 14, 2018

前言

从经典的 for 循环到 forEach() 方法,用于迭代数据集合的各种技术和方法比比皆是。但是现在比较流行的方法是 .map() 方法。

.map() 通过指定函数调用一个数组中每一项元素,来创建一个新数组。 .map() 是一种 non-mutating(非变异) 方法,它创建一个新数组,而不是只对调用数组进行更改的 mutating(变异) 方法。这可能很难记住。

语法:

array.map(function(currentValue,index,arr), thisValue)
  • currentValue:必须。当前元素的值
  • index:可选。当期元素的索引值
  • arr:可选。当期元素属于的数组对象
  • thisValue:可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值。可改变this指向,

map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。

map() 方法按照原始数组元素顺序依次处理元素。

注意: map() 不会对空数组进行检测。

注意: map() 不会改变原始数组。

在这篇文章中,我们将探讨一下 JavaScript 中 .map() 的 4 个值得注意的用法。让我们开始!

  • 在数组中的每一项元素上调用一个函数
  • 将字符串转换为数组
  • 在 JavaScript 库中用于渲染列表
  • 重新格式化数组对象
  • 小技巧使用案例

1. 在数组中的每一项元素上调用一个函数

如前所述,.map() 接受回调函数作为其参数之一,该函数的一个重要参数是由该函数处理的项的当前值。这是一个必需的参数。有了这个参数,我们可以修改数组中的每个单独项,并在其上创建一个新元素。这里有一个例子:

const sweetArray = [2, 3, 4, 5, 35]
const sweeterArray = sweetArray.map(sweetItem => {
return sweetItem * 2
})

console.log(sweetArray) // [2, 3, 4, 5, 35]
console.log(sweeterArray) // [4, 6, 8, 10, 70]

我们可以看到,原数组 sweetArray 并没有被修改,所以 .map() 是一种 non-mutating(非变异) 方法。这里值得一提的是 forEach() 方法,它是遍历数组,对原来的数据操作,会改变原数组。

这甚至可以进一步简化,使其更清洁:

// 创建一个要使用的函数
const makeSweeter = sweetItem => sweetItem * 2;

// 我们有一个数组
const sweetArray = [2, 3, 4, 5, 35];

// 调用我们制作的函数。更具可读性
const sweeterArray = sweetArray.map(makeSweeter);

console.log(sweeterArray); // [4, 6, 8, 10, 70]

拥有像 sweetArray.map(makeSweeter) 这样的代码可以让你在跳转到这段代码时更具可读性。

2.将字符串转换为数组

已知的 .map() 属于 Array 原型。 我们如何使用它将字符串转换为数组。 不用担心,我们不需要再开发一个方法来处理字符串,而是使用特殊的 .call() 方法。

JavaScript 中的所有内容都是对象,方法只是附加到这些对象的函数。 .call() 允许我们利用另一个对象的上下文。 因此,我们将数组中的 .map() 上下文复制到字符串。

.call() 可以传递参数,要使用的上下文和“参数原始函数的参数”。 听起来有点拗口? 这是一个例子:

const name = "Chuloo"
const map = Array.prototype.map

const newName = map.call(name, eachLetter => {
return `${eachLetter}a`
})

console.log(newName) // ["Ca", "ha", "ua", "la", "oa", "oa"]

这里,我们只是在String上使用 .map() 的上下文,并传递了 .map() 所期望的函数参数。 你可以看看控制台里打印出来的内容。

这类似于 String 的 .split() 方法,不过 .split() 方法只能在返回数组之前修改每个单独的字符串字符。

3.在 JavaScript 库中用于渲染列表

像 React 这样的 JavaScript 库利用 .map() 来渲染列表中的项目。这需要 JSX 语法,但是 .map() 方法包含在类似于 mustache 的 JSX 语法中。这是 React 组件的一个很好的例子。

import React from "react";
import ReactDOM from "react-dom";

const names = ["john", "sean", "mike", "jean", "chris"];

const NamesList = () => (
<div>
<ul>{names.map(name => <li key={name}> {name} </li>)}</ul>
</div>
);

const rootElement = document.getElementById("root");
ReactDOM.render(<NamesList />, rootElement);

如果你不熟悉 React ,那么我告诉这是 React 中的一个简单的无状态组件,它使用列表渲染div。 使用 .map() 渲染单个列表项以迭代最初创建的 names 数组。 此组件使用 ReactDOM 渲染 ID为 root 的 DOM 元素 。

4.重新格式化数组对象

如何处理数组中的对象? .map() 可用于迭代数组中的对象,并以与传统数组类似的方式,修改每个单独对象的内容 并返回一个新数组。 这个修改是基于回调函数中返回的内容来完成的。这里有一个例子:

const myUsers = [
{ name: 'chuloo', likes: 'grilled chicken' },
{ name: 'chris', likes: 'cold beer' },
{ name: 'sam', likes: 'fish biscuits' }
]

const usersByFood = myUsers.map(item => {
const container = {};

container[item.name] = item.likes;
container.age = item.name.length * 10;

return container;
})


console.log(usersByFood);
// [{chuloo: "grilled chicken", age: 60}, {chris: "cold beer", age: 50}, {sam: "fish biscuits", age: 30}]

我们所做的就是使用括号和点符号简单地修改数组中的每个对象。这个用例可以用于在前端应用程序上保存或解析之前处理或压缩接收到的数据。

5.小技巧使用案例

通常情况下,.map() 方法中的 callback 函数只需要接受一个参数,就是正在被遍历的数组元素本身。但这并不意味着 map 只给 callback 传了一个参数。这个思维惯性可能会让我们犯一个很容易犯的错误。 生成新数组元素的 callback 函数,有 三个参数:

  • currentValue ? callback 的第一个参数,数组中正在处理的当前元素,最常用的参数。
  • index ? callback 的第二个参数,数组中正在处理的当前元素的索引。
  • array ? callback 的第三个参数,map 方法被调用的数组。

来看一下例子:

// 下面的语句返回什么呢:
["1", "2", "3"].map(parseInt);
// 你可能觉的会是[1, 2, 3]
// 但实际的结果是 [1, NaN, NaN]

// 通常使用parseInt时,只需要传递一个参数.
// 但实际上,parseInt可以有两个参数.第二个参数是进制数.
// 可以通过语句"alert(parseInt.length)===2"来验证.
// map方法在调用callback函数时,会给它传递三个参数:当前正在遍历的元素, 
// 元素索引, 原数组本身.
// 第三个参数parseInt会忽视, 但第二个参数不会,也就是说,
// parseInt把传过来的索引值当成进制数来使用.从而返回了NaN.

function returnInt(element) {
return parseInt(element, 10);
}

['1', '2', '3'].map(returnInt); // [1, 2, 3]
// 意料之中的结果

// 也可以使用简单的箭头函数,结果同上
['1', '2', '3'].map( str => parseInt(str) );

// 一个更简单的方式:
['1', '2', '3'].map(Number); // [1, 2, 3]
// 与`parseInt` 不同,下面的结果会返回浮点数或指数:
['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300]

还有一个非常实用的小技巧,像 .map() ,.reduce(), .filter() 这些方法支持链式调用。例如:

var myArr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];

var result = myArr
.map(function(element) {
// 数值大于5的数值视为5
if (element > 5)
return 5;

return element;
})
.reduce(function(prev, element) {
// 与之前的数值加总,回传后代入下一轮的处理
return prev + element;
}, 0);

// 40
console.log(result);

这代码看着有点??率前桑扛行 pythonicx 提供的优化代码:

var myArr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
let result = myArr.map(m => m>5 ? 5 : m).reduce((x,y) => x+y);
console.log(result); // 40

小结

在这篇文章中,我们研究了 JavaScript 中 .map() 方法的主要用途。 需要注意的是,与其他方法结合使用时,.map() 的函数可以得到强大的扩展和利用。 尝试找出更多用例。

Javascript 相关文章推荐
jquery简单的拖动效果实现原理及示例
Jul 26 Javascript
javascript判断机器是否联网的2种方法
Aug 09 Javascript
JavaScript/Js脚本处理html元素的自定义属性解析(亲测兼容Firefox与IE)
Nov 25 Javascript
详解javascript中原始数据类型Null和Undefined
Dec 17 Javascript
简单谈谈javascript中this的隐式绑定
Feb 22 Javascript
实例讲解JavaScript中instanceof运算符的用法
Jun 08 Javascript
jQuery EasyUI中的日期控件DateBox修改方法
Nov 09 Javascript
超全面的vue.js使用总结
Feb 12 Javascript
微信小程序开发之map地图组件定位并手动修改位置偏差
Aug 17 Javascript
es6 for循环中let和var区别详解
Jan 12 Javascript
微信小程序自定义navigationBar顶部导航栏适配所有机型(附完整案例)
Apr 26 Javascript
jquery+ajax实现异步上传文件显示进度条
Aug 17 jQuery
微信小程序中的canvas 文字断行和省略号显示功能的处理方法
Nov 14 #Javascript
Vue 框架之动态绑定 css 样式实例分析
Nov 14 #Javascript
js删除对象/数组中null、undefined、空对象及空数组方法示例
Nov 14 #Javascript
Vue 框架之键盘事件、健值修饰符、双向数据绑定
Nov 14 #Javascript
Vue源码探究之状态初始化
Nov 14 #Javascript
vue使用laydate时间插件的方法
Nov 14 #Javascript
js使用Promise实现简单的Ajax缓存
Nov 14 #Javascript
You might like
php number_format() 函数通过千位分组来格式化数字的实现代码
2013/08/06 PHP
JSON用法之将PHP数组转JS数组,JS如何接收PHP数组
2015/10/08 PHP
jQuery)扩展jQuery系列之一 模拟alert,confirm(一)
2010/12/04 Javascript
在iframe里的页面编写js,实现在父窗口上创建动画效果展开和收缩的div(不变动iframe父窗口代码)
2011/12/20 Javascript
鼠标移到导航当前位置的LI变色处于选中状态
2013/08/23 Javascript
动态创建按钮的JavaScript代码
2016/01/29 Javascript
bootstrapfileinput实现文件自动上传
2016/11/08 Javascript
js实时获取窗口大小变化的实例代码
2016/11/18 Javascript
浅析script标签中的defer与async属性
2016/11/30 Javascript
jQuery使用ajax方法解析返回的json数据功能示例
2017/01/10 Javascript
vscode中Vue别名路径提示的实现
2020/07/31 Javascript
[02:07]DOTA2新英雄展现中国元素,完美“圣典”亮相央视
2016/12/19 DOTA
[43:53]OG vs EG 2019国际邀请赛淘汰赛 胜者组 BO3 第三场 8.22
2019/09/05 DOTA
[50:50]完美世界DOTA2联赛PWL S3 Galaxy Racer vs Phoenix 第一场 12.10
2020/12/13 DOTA
利用Python的Django框架生成PDF文件的教程
2015/07/22 Python
Python算法之求n个节点不同二叉树个数
2017/10/27 Python
Python爬虫包BeautifulSoup简介与安装(一)
2018/06/17 Python
python跳过第一行快速读取文件内容的实例
2018/07/12 Python
python爬取百度贴吧前1000页内容(requests库面向对象思想实现)
2019/08/10 Python
python 调用pyautogui 实时获取鼠标的位置、移动鼠标的方法
2019/08/27 Python
python能自学吗
2020/06/18 Python
详解python中的lambda与sorted函数
2020/09/04 Python
新加坡航空官方网站:Singapore Airlines
2016/10/13 全球购物
德国传统玻璃制造商:Cristalica
2018/04/23 全球购物
简单英文演讲稿
2014/01/01 职场文书
周年庆典邀请函范文
2014/01/24 职场文书
大学生家政服务项目创业计划书
2014/01/30 职场文书
最美孝心少年事迹材料
2014/08/15 职场文书
2014党支部对照检查材料思想汇报
2014/10/05 职场文书
大学生个人简历自荐信
2015/03/06 职场文书
当幸福来敲门观后感
2015/06/01 职场文书
工程主管竞聘书
2015/09/15 职场文书
2016幼儿教师自荐信范文
2016/01/28 职场文书
解决Pytorch dataloader时报错每个tensor维度不一样的问题
2021/05/28 Python
python调用ffmpeg命令行工具便捷操作视频示例实现过程
2021/11/01 Python
Win10鼠标宏怎么设置?win10系统鼠标宏的设置方法
2022/08/14 数码科技