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

前言

从经典的 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() 的函数可以得到强大的扩展和利用。 尝试找出更多用例。

(0)

相关推荐

  • JavaScript中利用Array和Object实现Map的方法

    本文实例讲述了JavaScript中利用Array和Object实现Map的方法.分享给大家供大家参考.具体如下: 昨天突然看到以前别人用JavaScript实现的Map感觉很不错,但是发现有个别方法有问题,顺便完善了下,添加了 remove .indexOf .values.clear等方法. /** * @author blune68 * @version 0.1, 07/27/12 * */ function Map(){ this.keys = new Array(); this.dat

  • JavaScript中循环遍历Array与Map的方法小结

    js循环数组各种方法 eg1: for (var i = 0; i < myStringArray.length; i++) { alert(myStringArray[i]); //Do something } eg2: Array.prototype.foo = "foo!"; var array = ['a', 'b', 'c']; for (var i in array) { alert(array[i]); } for(var i in this.$GLOBAL_DET

  • jQuery筛选数组之grep、each、inArray、map的用法及遍历json对象

    纯粹记录下几种用法: jquery grep()筛选遍历数组 $().ready( function(){ var array = [1,2,3,4,5,6,7,8,9]; var filterarray = $.grep(array,function(value){ return value > 5;//筛选出大于5的 }); for(var i=0;i<filterarray.length;i++){ alert(filterarray[i]); } for (key in filtera

  • Javascript中Array.prototype.map()详解

    在我们日常开发中,操作和转换数组是一件很常见的操作,下面我们来看一个实例: 复制代码 代码如下: var desColors = [],     srcColors = [         {r: 255, g: 255, b: 255 }, // White         {r: 128, g: 128, b: 128 }, // Gray         {r: 0,   g: 0,   b: 0   }  // Black     ]; for (var i = 0, ilen = sr

  • js获取通过ajax返回的map型的JSONArray的方法

    复制代码 代码如下: for(var i in datares){ if (datares.hasOwnProperty(i)) { sel.append("<option value='"+datares[i].deptid+"'>"+datares[i].deptname+"</option>"); } }

  • 详谈js遍历集合(Array,Map,Set)

    Array可以使用下标,Map和Set不能使用下标,ES6引入了iterable类型,Array,Map,Set都属于iterable类型,它们可以使用for...of循环来遍历: var a = ['A', 'B', 'C']; var s = new Set(['A', 'B', 'C']); var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]); for (var x of a) { // 遍历Array alert(x); } for (var

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

    前言 从经典的 for 循环到 forEach() 方法,用于迭代数据集合的各种技术和方法比比皆是.但是现在比较流行的方法是 .map() 方法. .map() 通过指定函数调用一个数组中每一项元素,来创建一个新数组. .map() 是一种 non-mutating(非变异) 方法,它创建一个新数组,而不是只对调用数组进行更改的 mutating(变异) 方法.这可能很难记住. 语法: array.map(function(currentValue,index,arr), thisValue)

  • JS实现斐波那契数列的五种方式(小结)

    下面是五种实现斐波那契数列的方法 循环 function fibonacci(n){ var res1 = 1; var res2 = 1; var sum = res2; for(var i = 1;i < n;i ++){ sum = res1 + res2; res1 = res2; res2 = sum; } return sum; } 普通递归 function fibonacci (n) { if ( n <= 1 ) {return 1}; return fibonacci(n

  • JavaScript常见的五种数组去重的方式

    大致介绍 JavaScript的数组去重问题在许多面试中都会遇到,现在做个总结 先来建立一个数组 var arr = [1,2,3,3,2,'我','我',34,'我的',NaN,NaN]; 第一种 思路:建立一个临时数组,用for循环去依次判断arr中的每个项在临时数组中是否有相同的值,如果没有则将这个值添加到临时数组,如果有相同的值则不添加,最后返回这个临时数组 代码: Array.prototype.removeDuplicate = function(){ var n = []; for

  • C#后台调用前台javascript的五种方法小结

    在网上找了找,发现有三种方法可以访问到前台代码: 第一种,OnClientClick (vs2003不支持这个方法) <asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="client_click()" OnClick="Button1_Click" /> client_click() 就是javascript的

  • 探究JavaScript中的五种事件处理程序方式

    我们知道JavaScript与HTML之间的交互是通过事件实现的.事件最早是在IE3和Netscape Navigator 2中出现的,当时是作为分担服务器运算负载的一种手段. 通俗地理解,事件就是用户或浏览器自身执行的某种操作.而事件处理程序即为响应某个事件的函数.抽出主干,即事件处理程序为函数.  我们又把事件处理程序称为事件侦听器.  事件处理程序是以"on"开头的,因此对于事件on的时间处理程序即为onclick.时间处理程序在JavaScript中大致有五种,下面会根据这五种

  • javascript中的五种基本数据类型

    [0]5种数据类型: [0.1]基本数据类型:Undefined.Null.Boolean.Number.String [0.1.1]基本类型值是指简单的数据段,5种基本类型是按值访问的,因为可以操作保存在变量中的实际值 [0.1.2]基本类型的值在内存中占据固定大小的空间,被保存在栈内存中.从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本. [0.1.3]不能给基本类型的值添加属性 [0.2]引用数据类型:Object [0.2.1]引用类型值是指那些可以由多个值构成的对象.js

  • 常见的PHP五种设计模式小结

    设计模式 一书将设计模式引入软件社区,该书的作者是 Erich Gamma.Richard Helm.Ralph Johnson 和 John Vlissides Design(俗称 "四人帮").所介绍的设计模式背后的核心概念非常简单.经过多年的软件开发实践,Gamma 等人发现了某些具有固定设计的模式,就像建筑师设计房子和建筑物一样,可以为浴室的位置或厨房的构造方式开发模板.使用这些模板或者说设计模式 意味着可以更快地设计更好的建筑物.同样的概念也适用于软件. 设计模式不仅代表着更

  • Zuul 实现网关转发的五种方式小结

    上图为一个微服务框架的简单示例,当有一个HTTP请求发送到服务器的时候,其实是先经过了Nginx的,再经过了网关,这里的网关就担任了拦截过滤的作用,既然拦截和过滤了,肯定就涉及到了请求的转发 转发我大致例了以下五种转发方式: 方式一:path+serviceId 方式 在spring_cloud的配置文件application.yml 文件中加入以下配置: server: port: 8888 #服务端口 spring: application: name: app-zuul-gateway #

  • Javascript中的五种数据类型详解

    Undefined 未定义.只有一个值undefined Null 只有一个值,null Boolean 在javascript中,只要逻辑表达式不返回undefined不返回null,就都是真的. 复制代码 代码如下: if(3) true if(null) false if(undefined) false Number String javascript中不存在char类型. 字符串定义可以用单引号,也可以用双引号. 复制代码 代码如下: <html> <head> <

  • jQuery插件开发的五种形态小结

    关于jQuery插件的开发自己也做了少许研究,自己也写过多个插件,在自己的团队了也分享过一次关于插件的课.开始的时候整觉的很复杂的代码,现在再次看的时候就清晰了许多.这里我把我自己总结出来的东西分享出来,帮助那些和我一样曾经遇到过同样问题的人. 我要做什么 我想要得到的javascript 插件应该会有以下几个特征 代码相对独立 链式操作 插件可配置 有可操作的方法,插件的生命周期可控制 配置可被缓存 可扩展 无冲突处理 事件代理,动态初始化 * 以下的代码均假设存在 jQuery 插件的第一形

随机推荐