从经典的 for 循环到forEach()
方法,用于迭代数据集合的各类技术和方法比比皆是。可是如今比较流行的方法是.map()
方法。前端
.map()
经过指定函数调用一个数组中每一项元素,来建立一个新数组。.map()
是一种 non-mutating(非变异) 方法,它建立一个新数组,而不是只对调用数组进行更改的 mutating(变异) 方法。这可能很难记住。react
在这篇文章中,咱们将探讨一下 JavaScript 中.map()
的 4 个值得注意的用法。让咱们开始!数组
在数组中的每一项元素上调用一个函数
将字符串转换为数组
在 JavaScript 库中用于渲染列表
从新格式化数组对象
小技巧使用案例dom
如前所述,.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() 方法,它是遍历数组,对原来的数据操做,会改变原数组。ui
这甚至能够进一步简化,使其更清洁:prototype
// 建立一个要使用的函数 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)
这样的代码可让你在跳转到这段代码时更具可读性。code
将字符串转换为数组
已知的.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()
方法只能在返回数组以前修改每一个单独的字符串字符。
像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 = () => (
{names.map(name =>
{name}
)}
); const rootElement = document.getElementById("root"); ReactDOM.render(
, rootElement);
若是你不熟悉 React ,那么我告诉这是 React 中的一个简单的无状态组件,它使用列表渲染div。 使用.map()
渲染单个列表项以迭代最初建立的names
数组。 此组件使用 ReactDOM 渲染 ID为 root 的 DOM 元素 。
如何处理数组中的对象?.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}]
咱们所作的就是使用括号和点符号简单地修改数组中的每一个对象。这个用例能够用于在前端应用程序上保存或解析以前处理或压缩接收到的数据。
一般状况下,.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);
在这篇文章中,咱们研究了 JavaScript 中 .map() 方法的主要用途。 须要注意的是,与其余方法结合使用时, .map() 的函数能够获得强大的扩展和利用。 尝试找出更多用例。 在评论区留下您的意见,问题和反馈,咱们将不胜感激!