目录
一、array.map()的使用与技巧
1.1、基本语法
array.map(callback(currentValue, index, array), thisArg)
callback:一个函数,用于处理每个元素,并返回处理后的值。
- currentValue:正在处理的当前元素。
- index(可选):正在处理的当前元素的索引。
- array(可选):调用 map() 的数组。
thisArg(可选):执行 callback 函数时,用作 this 的值。
1.2、返回值
返回一个新数组,结果为原始数组元素依次调用 callback 后的值(往往为一个新的数组)。
1.3、使用技巧
array.map()创建一个新数组,其结果是该数组中的每个元素(调用一个提供的函数)调用一个提供的函数后的返回值。这个方法对原数组不进行任何修改。
应用场景:数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等。其中应用函数常作为map操作中的其中一步,更多指一种封装和复用的思想而不是一种具体的需求。
1.3.1、数据转换与应用函数
假设我们有一个电子商务网站的订单数组,每个订单是一个对象,包含 id、date、items 和 shipping。每个 items 是一个对象数组,包含 name、price 和 quantity。
我们的目标是创建一个新的数组,其中每个元素是一个对象,包含订单的 id、订单总金额(所有商品价格和数量的总和)、订单日期以及基于总金额计算的税费(税费计算函数为 calculateTax(totalAmount),其中如果总金额小于1000,则税费为总金额的10%,否则为100)。
- // 创建一个新的数组,其中每个元素是一个对象,包含订单的 id、订单总金额、订单日期以及基于总金额计算的税费
- // 其中如果总金额小于1000,则税费为总金额的10%,否则为100
-
- // 示例订单数组
- const orders = [
- { id: 1, date: '2023-04-01', items: [{ name: 'Item1', price: 100, quantity: 2 }], shipping: 50 },
- { id: 2, date: '2023-04-02', items: [{ name: 'Item2', price: 200, quantity: 1 }], shipping: 30 },
- // ... 更多订单
- ];
-
- // 税费计算函数
- function calculateTax(totalAmount) {
- return totalAmount < 1000 ? totalAmount * 0.1 : 100;
- }
-
- // 创建新数组,包含每个订单的id, 总金额, 订单日期和税费
- const orderDetails = orders.map(order => {
- const totalAmount = order.items.reduce((sum, item) => sum + item.price * item.quantity, 0);
- const tax = calculateTax(totalAmount);
- return {
- id: order.id,
- totalAmount: totalAmount + order.shipping + tax, // 包括运费和税费的最终总金额
- date: order.date,
- tax: tax
- };
- });
-
- console.log(orderDetails);
-
-
- // 输出:
- [
- {
- id: 1,
- totalAmount: 300, // 100 * 2 (items) + 50 (shipping) + 20 (tax)
- date: '2023-04-01',
- tax: 20
- },
- {
- id: 2,
- totalAmount: 330, // 200 * 1 (item) + 30 (shipping) + 30 (tax)
- date: '2023-04-02',
- tax: 30
- },
- // ... 更多订单详情
- ]
1.3.2、创建派生数组
要创建派生数组,相比于直接通过for循环来“以旧换新”,array.map()比for、foreach还有非常不常用的while、do...while高级,代码清晰,可读性强,代码就看起来很优雅,如果都是嵌套循环和嵌套回调,看起来就是一团乱麻,可读性差,很不优雅。
举个例子:有一个员工信息的数组,每个员工对象包含 name、age 和 salary。我们想要创建一个新的数组,其中只包含年龄超过30岁的员工的姓名和工资。
- // 有一个员工信息的数组,每个员工对象包含 name、age 和 salary。我们想要创建一个新的数组,其中只包含年龄超过30岁的员工的姓名和工资。
-
- const employees = [
- { name: 'Alice', age: 25, salary: 70000 },
- { name: 'Bob', age: 32, salary: 80000 },
- { name: 'Charlie', age: 35, salary: 90000 },
- { name: 'David', age: 22, salary: 60000 }
- ];
-
- const olderEmployees = employees
- .filter(employee => employee.age > 30) // 筛选年龄超过30岁的员工
- .map(employee => ({
- name: employee.name,
- salary: employee.salary
- })); // 创建新数组,只包含姓名和工资
-
- console.log(olderEmployees);
-
- // 输出:
- [
- { name: 'Bob', salary: 80000 },
- { name: 'Charlie', salary: 90000 }
- ]
1.3.3、链式调用
有一个用户信息的数组,每个用户对象包含 id、name 和 isActive。我们想要获取所有活跃用户的姓名,并按照字母顺序排序。
- //有一个用户信息的数组,每个用户对象包含 id、name 和 isActive。我们想要获取所有活跃用户的姓名,并按照字母顺序排序
-
- const users = [
- { id: 1, name: 'Alice', isActive: true },
- { id: 2, name: 'Bob', isActive: false },
- { id: 3, name: 'Charlie', isActive: true },
- { id: 4, name: 'David', isActive: true }
- ];
-
- const activeUserNames = users
- .filter(user => user.isActive) // 筛选活跃用户
- .map(user => user.name) // 获取用户名
- .sort(); // 按照字母顺序排序
-
- console.log(activeUserNames);
-
-
- // 输出:
- // ['Alice', 'Charlie', 'David']
1.3.4、异步数据流处理
有一个用户列表,每个用户都有一个异步函数 fetchUserData 来获取用户的详细信息。我们想要获取所有用户的详细信息,并对结果进行处理。
- // 有一个用户列表,每个用户都有一个异步函数 fetchUserData 来获取用户的详细信息。我们想要获取所有用户的详细信息,并对结果进行处理。
-
- const users = [
- { id: 1, name: 'Alice' },
- { id: 2, name: 'Bob' },
- // ... 更多用户
- ];
-
- // 模拟异步获取用户详细信息的函数
- const fetchUserData = userId =>
- new Promise(resolve => setTimeout(() => resolve(`Data for user ${userId}`), 1000));
-
- // 使用 map() 和 Promise.all() 处理异步数据流
- const fetchAllUserData = users.map(user =>
- fetchUserData(user.id).then(data => ({ ...user, details: data }))
- );
-
- Promise.all(fetchAllUserData).then(usersWithData => {
- console.log(usersWithData); // 输出处理后包含每个用户详细信息的数组
- });
1.3.5、复杂API请求梳理
有时候需要从不同的API端点获取数据,并将这些数据汇总到一个数组中。
- // 需要从不同的API端点获取数据,并将这些数据汇总到一个数组中。
-
- const apiEndpoints = [
- 'https://api.example.com/data1',
- 'https://api.example.com/data2',
- // ... 更多API端点
- ];
-
- // 模拟异步API请求
- const fetchDataFromApi = url =>
- new Promise(resolve => setTimeout(() => resolve(`Data from ${url}`), 500));
-
- // 使用 map() 来对每个API端点发起请求
- const fetchAllData = apiEndpoints.map(endpoint =>
- fetchDataFromApi(endpoint)
- );
-
- Promise.all(fetchAllData).then(allData => {
- console.log(allData); // 输出包含所有API请求结果的数组
- });
1.3.6、提供DOM操作
假设我们有一个用户列表,我们想要为每个用户创建一个列表项并将其添加到页面上的一个列表中。
- // 假设我们有一个用户列表,我们想要为每个用户创建一个列表项并将其添加到页面上的一个列表中。
-
- const users = [
- { id: 1, name: 'Alice' },
- { id: 2, name: 'Bob' },
- // ... 更多用户
- ];
-
- // 选择页面上的列表元素
- const userList = document.getElementById('user-list');
-
- // 使用 map() 生成每个用户的列表项
- const listItems = users.map(user => {
- const li = document.createElement('li');
- li.textContent = `User ${user.name}`;
- return li;
- });
-
- // 将所有列表项添加到列表中
- listItems.forEach(item => userList.appendChild(item));
1.3.7、用来搜索和过滤
假设我们有一个商品列表,我们想要根据用户的搜索输入来过滤商品。
- // 假设我们有一个商品列表,我们想要根据用户的搜索输入来过滤商品。
-
- const products = [
- { id: 1, name: 'Apple', category: 'Fruits' },
- { id: 2, name: 'Banana', category: 'Fruits' },
- // ... 更多商品
- ];
-
- // 用户输入的搜索关键词
- const searchQuery = 'Apple';
-
- // 使用 map() 和 filter() 进行搜索和过滤
- const filteredProducts = products
- .filter(product => product.name.includes(searchQuery))
- .map(product => ({
- id: product.id,
- name: product.name,
- // 其他需要展示的信息
- }));
-
- console.log(filteredProducts); // 输出匹配搜索关键词的商品列表
二、总结
array.map()可以用来数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求梳理、提供DOM操作、用来搜索和过滤等,比for好用太多了,主要是写法简单,并且非常直观,并且能提升代码的可读性,也就提升了Long Term代码的可维护性。
W3school传送门(我的博客更详细):JavaScript Array map() 方法
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
评论记录:
回复评论: