简介
遍历序列可以用来访问和显示序列中的元素--但更多时候,它是为了在每个或某些元素上运行一个操作。
**注:**对一个序列的每个元素应用一个函数,并将转换后的结果返回到一个新的序列中,这被称为映射,其中原始序列的每个元素,Ex ,映射到新序列的一个潜在的转换元素,Exi 。
像大多数语言一样,JavaScript有一个映射操作的有效实现,它被内置到Array 类中。
在本指南中,你将学习如何使用JavaScript的
map()方法,以及它是如何工作的,在实际的代码例子上。
JavaScript的*map()*方法
让我们通过for-loop 语法,看看我们如何对每个元素应用某些方法。假设我们有一组分数,并希望给每个人加5分,以协助提高分数。
const mathScores = [39, 50, 45, 41, 50];
let newScores = [];
for (let i = 0; i < mathScores.length; i++) {
newScores.push(mathScores[i] + 5);
}
console.log(newScores); // [44,55,50,46,55]
在上面的代码中,我们在mathScores 数组中循环,给每个成员增加5分,然后将新的分数推到newScores 数组中。
这是一个非常标准的程序,与map() 的工作非常相似。
Array.map()方法遍历一个数组,并对每个元素应用回调函数,在一个新的数组中返回结果元素。
语法
该方法的语法是相当简单的。
const newArray = oldArray.map((currentValue, index, array)=>{
// Do stuff with currentValue
})
index 和array 是可选的,可以用来访问currentValue 的索引和原始数组本身。
newArray- 应用 函数后,返回的新数组。map()oldArray- 函数对原始数组进行操作,并不改变它。map()currentValue- 函数在步骤 中处理的值,其中函数定义了在步骤 中发生的事情。map()XXindex- 当前值的索引。array- 一个可选的参数,指向原始数组。
为了获得直观的视觉体验--你可以尝试记录这些值,并只返回原来的值,不做任何改变。
const mathScores = [39, 50, 45, 41, 50];
mathScores.map((currentValue, index, array) => {
console.log('Current value:' + currentValue);
console.log('Index:' + index);
console.log('Array:' + array);
return currentValue;
})
"Current value:39"
"Index:0"
"Array:39,50,45,41,50"
...
"Current value:50"
"Index:4"
"Array:39,50,45,41,50"
*map()*是如何工作的?
map() 函数,为了所有的实际目的,需要元素来工作--但是如果你调用map() 的数组是空的,它将只是返回一个空数组。它可以与箭头函数或普通函数一起使用。
在ES6之前,你通常将回调定义为。
const codes = [101, 201, 301, 303, 202];
let mathCodes = codes.map(function(code) {
return `mth${code}`;
});
console.log(mathCodes); //["mth101","mth201","mth301","mth303","mth202"]
然而,在ES6中,你可以使用箭头函数来使代码更简洁。
const codes = [101, 201, 301, 303, 202];
let mathCodes = codes.map((code)=>{
return `mth${code}`;
});
console.log(mathCodes); //["mth101","mth201","mth301","mth303","mth202"]
map() 示例
让我们来看看map() 函数的几个例子!例如,我们来计算列表中每个数字的平方根。
const numbers = [9, 36, 64, 144];
let squareRoots = numbers.map((number) => {
return Math.sqrt(number);
});
console.log(squareRoots); // [3,6,8,12]
或者,我们可以将每个元素映射为其长度。
const names = ["Bilbo", "Gandalf", "Nazgul"];
let lengths = names.map((name) => name.length);
console.log(lengths); // [5,7,6]
或者,我们可以将每个学生对象映射到他们的名字和姓氏。
const students = [
{firstName : "John", lastName: "Doe"},
{firstName : "Stephen", lastName: "Matt"},
{firstName : "Abigail", lastName: "Susu"}
];
let studentsNames = students.map(student => {
return `${student.firstName} ${student.lastName}`;
})
console.log(studentsNames); // ["John Doe","Stephen Matt","Abigail Susu"]
map() 函数在前端的一个真正常见的用例是将数据包裹在HTML中。
let cont = document.getElementById('#container');
let users = [
{ firstName : "John", lastName: "Doe", age: 17 },
{ firstName : "Stephen", lastName: "Matt", age: 16 },
{ firstName : "Abigail", lastName: "Susu", age: 15 }
];
let singleUser = users.map((user)=>{
// Let's add the firstname and lastname together
let fullName = user.firstName + ' ' + user.lastName;
return `
<h3 class='name'>${fullName}</h3>
<p class="age">${user.age}</p>
`
});
container.innerHTML = singleUser;
*map()*与其他迭代器方法的比较?
map() 是JavaScript中迭代器方法的一个例子,了解什么时候你想利用哪种迭代器方法是非常有用的。迭代器方法使你能够在一个数组中的所有对象上进行循环,以执行特定的操作。
当决定是否利用map() 函数时,最好考虑一下其他的迭代器技术是否更合适。
下面是JavaScript中的一些额外的迭代器方法。
- reduce()。减少操作是函数式编程中最强大的操作之一,通常涉及将一个向量减少到一个标量(一个值的列表,到一个单一的值)。这可以是对一个数组中的所有值进行求和,找到平均数、最小值或最大值,或者以任何其他方式将一个较长的数据集减少到一个较小的数据集,源于原始数据。
- filter()。过滤允许你从一个列表中过滤出不符合某些特定标准的项目,并返回一个符合标准的剩余项目的数组。
- forEach()。类似于
for...loop,forEach(),对列表中的每个项目执行一个函数。它允许你在一个数组中进行循环,并对每一个项目执行工作。
在某种程度上,这引出了一个问题。
map()和forEach()之间有什么区别?
map() vs forEach()
因为这两个方法都是通过一个数组运行,并用于对每个成员应用一个函数,所以map() 和forEach() 方法可能看起来极其相似。
这两个方法的主要区别是:map() 函数返回一个新的数组,而forEach() 方法则没有,它改变了原来的数组。
此外,在map() 函数的每一次迭代中,你将return 一个被转换的元素。使用forEach() ,你不返回它们,但可以在上面运行函数,就地改变元素。虽然,你甚至不需要在元素上运行一个函数!
这使得forEach() ,当它涉及到,比如说,记录值,而不改变它们时,更可取。
const characters = ['z', 'y', 'x', 'w'];
characters.forEach(character => {
console.log(character);
});
而如果你的目的是改变元素,map() 是首选。
在其他数组方法中使用map()
map() 方法来自于函数式编程--对于函数式编程,链式方法就像呼吸一样自然。函数式操作的连锁是非常普遍的,并且可以提供非常复杂的操作管道。
让我们来看看如何将map() 与Array 类的其他一些函数式方法连锁起来。
使用map()和filter()
过滤通常是流水线中的第一个操作,因为对可能不包括在结果中的元素运行操作是没有效率的,除非你过滤的标准取决于流水线中的其他操作。
一个常见的步骤顺序是根据某个标准filter() 一个数组,然后再map() 剩余的元素。
让我们创建一个学生数组来过滤和映射。
const mathStudents = [
{
name: 'Jane',
score: 60,
enrollmentYear: 2019
},
{
name: 'Emmy',
score: 40,
enrollmentYear: 2020
},
{
name: 'John',
score: 43,
enrollmentYear: 2019
},
{
name: 'Linda',
score: 20,
enrollmentYear: 2019
}
]
现在,让我们根据学生的年份来过滤--只得到上一代的学生,然后映射他们的分数。
我们将把分数映射为 "及格"/"不及格 "的等级,以获得更符合人类需要的格式。
const passingStudents = mathStudents
.filter((student) => student.enrollmentYear < 2020)
.map((student) => {
if (student.score > 40) {
return student.name + ': passing'
} else return student.name + ': not passing'
});
console.log(passingStudents); // ["Jane: passing","John: passing","Linda: not passing"]
使用map()与reverse()
有时你可能需要在执行其他操作之前或之后反转一个数组。这可以通过使用reverse() 函数很容易地完成。
const numbers = [21, 32, 43, 54, 65];
const newNumbers = numbers.map((number) => number * 2).reverse();
console.log(numbers); // [21,32,43,54,65]
console.log(newNumbers); // [130,108,86,64,42]
我们在循环的最后插入了reverse() 函数,这样它就可以反转得到的数组。如果我们把reverse() 调用放在map() 调用之前--我们实际上会反转原始数组,并映射其元素,而不是反转新的结果数组。
const numbers = [21, 32, 43, 54, 65];
const newNumbers = numbers.reverse().map((number) => number * 2);
console.log(numbers); // [65,54,43,32,21]
console.log(newNumbers); // [130,108,86,64,42]
在一个对象上使用map()
在使用对象静态方法(Object.keys(),Object.values(), 和Object.entries() )获得值、键或键值对之后,也可以在对象上使用map() 函数。因为这些对象静态方法中的每一个都会产生一个数组,map() 可以简单地与每一个数组相连接。
const scores = { math: 50, English: 70, Physics: 45, Agric: 60 };
let newScores = Object.values(scores).map((score) => score + 5);
console.log(newScores); // [55,75,50,65]
结论
在本指南中,我们看了一下JavaScript中的map() 方法。
该方法遍历一个数组,对数组中的每个元素应用一个函数,并将新的元素序列作为一个新数组返回。我们通过实际例子看了该方法的语法、参数和用法。
此外,我们还比较了map() 方法和forEach() 方法,并探讨了如何将map() 与filter() 、reverse() 和对象相连接。