JavaScript map()方法超全介绍
文章目录
在 JavaScript 中, map() 是数组的一个常用方法,它创建一个新数组,其结果是该数组中的每个元素调用一次提供的函数后的返回值。
map() 的基本语法:
array.map(function(currentValue, index, array){// 返回新值}, thisValue);一 、主要特点:
- 不会改变原数组,而是返回一个新数组
- 新数组的长度与原数组相同
- 对数组中的每个元素都执行一次回调函数
二、示例:
- 基本用法 - 将数字数组翻倍
const numbers =[1,2,3,4,5];const doubled = numbers.map(num=> num *2); console.log(doubled);// [2, 4, 6, 8, 10] console.log(numbers);// [1, 2, 3, 4, 5] (原数组不变)- 处理对象数组
const users =[{name:'Alice',age:25},{name:'Bob',age:30},{name:'Charlie',age:35}];// 提取所有用户名const names = users.map(user=> user.name); console.log(names);// ["Alice", "Bob", "Charlie"]// 计算每个人5年后的年龄const agesInFiveYears = users.map(user=>({...user,age: user.age +5}));- 转换数据格式
const numbers =[1,2,3];const numberStrings = numbers.map(num=>`Number: ${num}`); console.log(numberStrings);// ["Number: 1", "Number: 2", "Number: 3"]- 使用索引参数
const fruits =['apple','banana','cherry'];const indexedFruits = fruits.map((fruit, index)=>`${index +1}. ${fruit}`); console.log(indexedFruits);// ["1. apple", "2. banana", "3. cherry"]map() 是函数式编程中常用的方法,经常与 filter()、reduce() 等数组方法配合使用,处理和转换数据。注意不要在 map() 中进行没有返回值的操作(如仅打印),这时候应该使用 forEach() 更合适。
三、map() 方法和 forEach() 方法有什么区别?
在 JavaScript 中,map() 和 forEach() 都是用于遍历数组的方法,但它们的设计目的和使用场景有显著区别:
1. 返回值不同
forEach():没有返回值(返回 undefined),仅用于执行遍历操作。
const numbers =[1,2,3];const result = numbers.forEach(num=> num *2); console.log(result);// undefinedmap():返回一个新数组,新数组的元素是原数组每个元素经过回调函数处理后的结果。
const numbers =[1,2,3];const doubled = numbers.map(num=> num *2); console.log(doubled);// [2, 4, 6](新数组)2. 用途不同
forEach():适合执行副作用操作(如打印、修改外部变量、DOM操作等),不关心返回值时使用。
// 打印数组元素(副作用)const fruits =['apple','banana']; fruits.forEach(fruit=> console.log(fruit));map():适合数据转换场景,需要根据原数组生成新数组时使用(如格式转换、值计算等)。
// 将对象数组转换为只包含名称的数组const users =[{name:'Alice'},{name:'Bob'}];const names = users.map(user=> user.name);// ['Alice', 'Bob']3. 链式调用支持
forEach():由于返回 undefined,无法进行链式调用。
// 无效的链式调用(会报错) numbers.forEach(...).filter(...)// 错误:Cannot read property 'filter' of undefinedmap():由于返回新数组,可以直接链式调用其他数组方法(如 filter()、reduce() 等)。
const numbers =[1,2,3,4];const sumOfDoubledEvens = numbers .filter(num=> num %2===0)// 筛选偶数 [2, 4].map(num=> num *2)// 翻倍 [4, 8].reduce((sum, num)=> sum + num,0);// 求和 124. 中断遍历
两者都无法通过 break 或 continue 中断遍历(这一点与 for 循环不同)。
如果需要中断遍历,应使用 for 循环或 some()/every()(通过返回 true 提前退出)。
5. 总结
| 特性 | map() | forEach() |
|---|---|---|
| 返回值 | 新数组(转换后的结果) | 无(undefined) |
| 用途 | 数据转换生成新数组 | 执行副作用操作 |
| 链式调用 | 支持 | 不支持 |
| 典型场景 | 格式转换、值计算 | 打印、DOM操作、修改外部变量 |
最佳实践:
- 当需要基于原数组生成新数组时,用
map(); - 当仅需要遍历执行操作,不需要返回新数组时,用
forEach()。
四、不使用map()方法的情况下实现类似的功能
如果不使用 map() 方法,我们可以通过其他方式实现类似的功能——即遍历数组并对每个元素进行处理,最终返回一个新的转换后数组。最常见的方式是使用 for 循环、for...of 循环或 forEach() 方法。
以下是几种实现方式:
1. 使用 for 循环(最基础的方式)
functioncustomMap(array, callback){// 创建一个新数组用于存储结果const result =[];// 遍历原数组for(let i =0; i < array.length; i++){// 对每个元素执行回调函数,并将结果存入新数组 result.push(callback(array[i], i, array));}// 返回转换后的新数组return result;}// 使用示例const numbers =[1,2,3,4];const doubled =customMap(numbers,(num)=> num *2); console.log(doubled);// [2, 4, 6, 8]const names =[{first:'John',last:'Doe'},{first:'Jane',last:'Smith'}];const fullNames =customMap(names,(person)=>`${person.first}${person.last}`); console.log(fullNames);// ["John Doe", "Jane Smith"]2. 使用 for...of 循环(更简洁的遍历方式)
functioncustomMap(array, callback){const result =[];let index =0;// for...of 遍历元素,同时记录索引for(const item of array){ result.push(callback(item, index, array)); index++;}return result;}// 使用示例const fruits =['apple','banana','cherry'];const uppercaseFruits =customMap(fruits,(fruit)=> fruit.toUpperCase()); console.log(uppercaseFruits);// ["APPLE", "BANANA", "CHERRY"]3. 使用 forEach() 方法
虽然 forEach() 本身没有返回值,但可以利用它遍历数组并收集结果:
functioncustomMap(array, callback){const result =[]; array.forEach((item, index, arr)=>{ result.push(callback(item, index, arr));});return result;}// 使用示例const numbers =[10,20,30];const withSuffix =customMap(numbers,(num)=>`${num}px`); console.log(withSuffix);// ["10px", "20px", "30px"]4. 这些实现的核心思路:
- 创建一个空数组用于存储转换后的结果
- 遍历原数组的每个元素
- 对每个元素执行回调函数(接收当前元素、索引、原数组三个参数)
- 将回调函数的返回值存入结果数组
- 遍历结束后返回结果数组
这种自定义实现和原生 map() 方法的核心逻辑完全一致,只是原生方法经过了引擎优化,性能更好。通过这种方式,我们可以更深入理解 map() 的工作原理——它本质上就是一个"遍历-转换-收集"的过程。