JS中的遍历

一.基础使用

1. 遍历数组

for 循环
const numbers = [1, 2, 3, 4, 5];

for (let i = 0; i < numbers.length; i++) {
  console.log(numbers[i]);
}

// 输出:
// 1
// 2
// 3
// 4
// 5
forEach
const numbers = [1, 2, 3, 4, 5];

numbers.forEach((number, index) => {
  console.log(`Index: ${index}, Number: ${number}`);
});

// 输出:
// Index: 0, Number: 1
// Index: 1, Number: 2
// Index: 2, Number: 3
// Index: 3, Number: 4
// Index: 4, Number: 5
map
const numbers = [1, 2, 3, 4, 5];

const doubled = numbers.map(number => number * 2);
console.log(doubled);

// 输出: [2, 4, 6, 8, 10]
filter
const numbers = [1, 2, 3, 4, 5];

const evenNumbers = numbers.filter(number => number % 2 === 0);
console.log(evenNumbers);

// 输出: [2, 4]
reduce
const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum);

// 输出: 15

2. 遍历对象

for…in
const person = { name: 'Alice', age: 30, city: 'New York' };

for (const key in person) {
  if (person.hasOwnProperty(key)) {
    console.log(`${key}: ${person[key]}`);
  }
}

// 输出:
// name: Alice
// age: 30
// city: New York
Object.keys
const person = { name: 'Alice', age: 30, city: 'New York' };

Object.keys(person).forEach(key => {
  console.log(`${key}: ${person[key]}`);
});

// 输出:
// name: Alice
// age: 30
// city: New York
Object.entries
const person = { name: 'Alice', age: 30, city: 'New York' };

Object.entries(person).forEach(([key, value]) => {
  console.log(`${key}: ${value}`);
});

// 输出:
// name: Alice
// age: 30
// city: New York

3. 遍历其他可迭代对象

for…of
const numbers = [1, 2, 3, 4, 5];

for (const number of numbers) {
  console.log(number);
}

// 输出:
// 1
// 2
// 3
// 4
// 5

4. 遍历 Set 和 Map

Set
const set = new Set([1, 2, 3, 4, 5]);

for (const value of set) {
  console.log(value);
}

// 输出:
// 1
// 2
// 3
// 4
// 5
Map
const map = new Map([
  ['name', 'Alice'],
  ['age', 30],
  ['city', 'New York']
]);

for (const [key, value] of map) {
  console.log(`${key}: ${value}`);
}

// 输出:
// name: Alice
// age: 30
// city: New York

总结

  • 数组遍历:使用 for 循环、forEachmapfilterreduce 方法。
  • 对象遍历:使用 for...in 循环、Object.keysObject.entries 方法。
  • 其他可迭代对象遍历:使用 for...of 循环。

这些示例展示了如何在实际应用中遍历不同的数据结构,并给出了具体的输出结果。希望这些示例对您有所帮助!如果您有任何其他问题或需要更详细的解释,请随时提问。

栗子🌰

当然,我会提供一些更复杂的示例,这些示例更加贴近实际项目中的应用场景。我们将处理一些更复杂的业务逻辑,比如处理用户权限、处理数据库查询结果、处理API响应等。

1. 用户权限处理

假设我们有一个用户列表和一个角色列表,我们需要根据用户的权限来过滤用户列表。

const users = [
  { id: 1, name: 'Alice', role: 'admin' },
  { id: 2, name: 'Bob', role: 'user' },
  { id: 3, name: 'Charlie', role: 'admin' },
  { id: 4, name: 'Diana', role: 'user' }
];

const roles = [
  { id: 1, name: 'admin', permissions: ['read', 'write'] },
  { id: 2, name: 'user', permissions: ['read'] }
];

// 获取具有特定权限的用户列表
const getUsersWithPermission = (users, roles, permission) => {
  const usersWithPermission = users.filter(user => {
    const role = roles.find(role => role.name === user.role);
    return role && role.permissions.includes(permission);
  });

  return usersWithPermission;
};

// 获取具有 'write' 权限的用户
const usersWithWritePermission = getUsersWithPermission(users, roles, 'write');

// 输出结果
const result = `
Users with 'write' permission:
${usersWithWritePermission.map(user => `- ${user.name}`).join('\n')}
`;

console.log(result);

// 输出:
// Users with 'write' permission:
// - Alice
// - Charlie

2. 数据库查询结果处理

假设我们从数据库获取了一组数据,需要对数据进行处理以生成报表。

const dbResults = [
  { id: 1, name: 'Alice', department: 'HR', salary: 5000 },
  { id: 2, name: 'Bob', department: 'Engineering', salary: 8000 },
  { id: 3, name: 'Charlie', department: 'HR', salary: 5500 },
  { id: 4, name: 'Diana', department: 'Sales', salary: 7000 }
];

// 计算每个部门的平均工资
const averageSalaryByDepartment = dbResults.reduce((acc, result) => {
  if (!acc[result.department]) {
    acc[result.department] = { total: 0, count: 0 };
  }
  acc[result.department].total += result.salary;
  acc[result.department].count++;
  return acc;
}, {});

// 输出结果
const result = `
Average Salary by Department:
${Object.entries(averageSalaryByDepartment).map(([department, data]) => {
  const averageSalary = data.total / data.count;
  return `- ${department}: $${averageSalary.toFixed(2)}`;
}).join('\n')}
`;

console.log(result);

// 输出:
// Average Salary by Department:
// - HR: $5250.00
// - Engineering: $8000.00
// - Sales: $7000.00

3. API 响应处理

假设我们从 API 获取了一些数据,需要处理这些数据以生成用户友好的输出。

const apiResponse = [
  { id: 1, name: 'Alice', age: 30, gender: 'female' },
  { id: 2, name: 'Bob', age: 25, gender: 'male' },
  { id: 3, name: 'Charlie', age: 35, gender: 'male' },
  { id: 4, name: 'Diana', age: 28, gender: 'female' }
];

// 分组数据按性别
const groupByGender = (data, key) => {
  return data.reduce((acc, item) => {
    if (!acc[item[key]]) {
      acc[item[key]] = [];
    }
    acc[item[key]].push(item);
    return acc;
  }, {});
};

// 按性别分组
const groupedData = groupByGender(apiResponse, 'gender');

// 输出结果
const result = `
Grouped Data by Gender:
${Object.entries(groupedData).map(([gender, users]) => {
  const formattedUsers = users.map(user => `- ${user.name} (${user.age} years old)`);
  return `- ${gender}:
${formattedUsers.join('\n')}`;
}).join('\n\n')}
`;

console.log(result);

// 输出:
// Grouped Data by Gender:
// - female:
// - Alice (30 years old)
// - Diana (28 years old)
//
// - male:
// - Bob (25 years old)
// - Charlie (35 years old)

4. 电子商务订单处理

假设我们有一个订单列表,需要处理订单数据以生成销售报告。

const orders = [
  { orderId: 1, productId: 1, quantity: 2, status: 'completed', date: '2023-08-01' },
  { orderId: 2, productId: 2, quantity: 1, status: 'pending', date: '2023-08-02' },
  { orderId: 3, productId: 1, quantity: 1, status: 'completed', date: '2023-08-03' },
  { orderId: 4, productId: 3, quantity: 3, status: 'completed', date: '2023-08-04' }
];

// 统计每天的订单数量
const dailyOrdersCount = orders.reduce((acc, order) => {
  if (!acc[order.date]) {
    acc[order.date] = 0;
  }
  acc[order.date]++;
  return acc;
}, {});

// 输出结果
const result = `
Daily Orders Count:
${Object.entries(dailyOrdersCount).map(([date, count]) => `- ${date}: ${count} orders`).join('\n')}
`;

console.log(result);

// 输出:
// Daily Orders Count:
// - 2023-08-01: 1 orders
// - 2023-08-02: 1 orders
// - 2023-08-03: 1 orders
// - 2023-08-04: 1 orders

5. 日志分析

假设我们有一系列的日志条目,需要分析这些日志来找出特定的操作记录。

const logEntries = [
  { id: 1, timestamp: '2023-08-01T12:00:00Z', operation: 'login', userId: 1 },
  { id: 2, timestamp: '2023-08-01T12:05:00Z', operation: 'logout', userId: 1 },
  { id: 3, timestamp: '2023-08-01T12:10:00Z', operation: 'login', userId: 2 },
  { id: 4, timestamp: '2023-08-01T12:15:00Z', operation: 'update', userId: 1 },
  { id: 5, timestamp: '2023-08-01T12:20:00Z', operation: 'logout', userId: 2 }
];

// 获取特定用户的登录和登出记录
const getUserLoginLogout = (entries, userId) => {
  const filteredEntries = entries.filter(entry => entry.userId === userId && (entry.operation === 'login' || entry.operation === 'logout'));
  return filteredEntries;
};

// 获取用户 ID 1 的登录和登出记录
const loginLogoutRecords = getUserLoginLogout(logEntries, 1);

// 输出结果
const result = `
Login/Logout Records for User 1:
${loginLogoutRecords.map(entry => `- ${entry.operation} at ${entry.timestamp}`).join('\n')}
`;

console.log(result);

// 输出:
// Login/Logout Records for User 1:
// - login at 2023-08-01T12:00:00Z
// - logout at 2023-08-01T12:05:00Z

这些示例涵盖了不同的业务场景,并使用了模板字符串来格式化输出结果,使其更具可读性。希望这些示例对您有所帮助!如果您有其他具体的需求或想要探讨更多应用场景,请随时告诉我。

更真实栗子🌰

当然,下面是几个更复杂的示例,每个示例都包含了详细的注释和输出的注释,以帮助您更好地理解代码的逻辑和功能。

1. 电商系统的订单处理与库存管理

场景描述
在一个电商系统中,当用户下单后,系统需要检查商品库存是否充足,如果库存不足,则取消订单并通知用户。同时,系统还需要记录订单状态的变化,以便后续跟踪和分析。

代码实现

// 定义订单类
class Order {
  constructor(id, items, customer) {
    this.id = id; // 订单ID
    this.items = items; // 订单中的商品项
    this.customer = customer; // 下单客户信息
    this.status = 'created'; // 初始状态为创建
    this.history = [{ timestamp: new Date(), status: 'created' }]; // 订单状态变更历史
  }

  // 放置订单
  place() {
    this.status = 'placed';
    this.history.push({ timestamp: new Date(), status: 'placed' });
  }

  // 取消订单
  cancel(reason) {
    this.status = 'canceled';
    this.history.push({ timestamp: new Date(), status: 'canceled', reason });
  }

  // 异步处理库存检查
  async processInventoryCheck(inventoryService) {
    for (let item of this.items) {
      let availableStock = await inventoryService.getStock(item.product.id); // 获取商品库存
      if (availableStock < item.quantity) { // 库存不足
        this.cancel(`Insufficient stock for product ${item.product.name}`); // 取消订单
        return;
      }
      // 如果库存足够,则减少库存
      await inventoryService.reduceStock(item.product.id, item.quantity);
    }
    this.place(); // 放置订单
  }
}

// 定义商品类
class Product {
  constructor(id, name, price, stock) {
    this.id = id; // 商品ID
    this.name = name; // 商品名称
    this.price = price; // 商品价格
    this.stock = stock; // 商品库存
  }
}

// 定义库存服务类
class InventoryService {
  constructor() {
    this.products = [
      new Product(1, 'Laptop', 1200, 10), // 初始化商品列表
      new Product(2, 'Keyboard', 50, 100),
      new Product(3, 'Monitor', 300, 5)
    ];
  }

  // 获取商品库存
  async getStock(productId) {
    let product = this.products.find(p => p.id === productId); // 查找商品
    return product ? product.stock : 0; // 返回库存量
  }

  // 减少商品库存
  async reduceStock(productId, quantity) {
    let product = this.products.find(p => p.id === productId); // 查找商品
    if (product) {
      product.stock -= quantity; // 减少库存
    }
  }
}

// 创建订单和处理流程
const inventoryService = new InventoryService();

// 创建订单实例
const order = new Order(
  1,
  [
    { product: new Product(1, 'Laptop', 1200, 1), quantity: 1 }, // 订单中的商品项
    { product: new Product(2, 'Keyboard', 50, 5), quantity: 1 }
  ],
  { name: 'John Doe', email: 'john.doe@example.com' } // 客户信息
);

// 处理订单
order.processInventoryCheck(inventoryService).then(() => {
  console.log('Order processed:', order);
  // 输出:
  // Order processed: Order { id: 1, items: Array[2], customer: {…}, status: 'placed', history: Array[2] }
  // 其中 history 数组记录了订单的状态变化历史
});

// 输出订单状态变更历史
console.log('Order History:', order.history);
// 输出:
// Order History: [ { timestamp: [Date], status: 'created' }, { timestamp: [Date], status: 'placed' } ]

2. 社交媒体平台的消息推送

场景描述
在社交媒体平台上,用户可以关注其他用户,并接收他们发布的新动态。系统需要能够及时地推送新动态给相关的关注者。

代码实现

// 定义用户类
class User {
  constructor(username) {
    this.username = username; // 用户名
    this.posts = []; // 用户发布的动态
    this.followers = new Set(); // 关注者列表
  }

  // 关注用户
  follow(user) {
    user.followers.add(this);
  }

  // 取消关注用户
  unfollow(user) {
    user.followers.delete(this);
  }

  // 发布动态
  post(content) {
    this.posts.push({
      id: this.posts.length + 1, // 动态ID
      content, // 动态内容
      timestamp: new Date(), // 发布时间戳
      author: this // 动态作者
    });
    this.notifyFollowers(); // 通知关注者
  }

  // 通知关注者
  notifyFollowers() {
    for (let follower of this.followers) {
      follower.receiveNotification(this); // 接收通知
    }
  }
}

// 定义接收通知方法
User.prototype.receiveNotification = function(author) {
  console.log(`${author.username} posted: ${author.posts[author.posts.length - 1].content}`);
  // 输出:
  // alice posted: Hello world!
  // alice posted: Goodbye!
};

// 创建用户和模拟发布动态
const alice = new User('alice');
const bob = new User('bob');
const charlie = new User('charlie');

// 用户 bob 和 charlie 关注 alice
bob.follow(alice);
charlie.follow(alice);

// alice 发布两条动态
alice.post('Hello world!');
alice.post('Goodbye!');

// 输出关注者收到的通知

3. 在线教育平台的成绩管理

场景描述
在线教育平台允许教师上传成绩,并允许学生查看自己的成绩。此外,系统还需要能够计算学生的平均成绩,并发送电子邮件通知给学生和家长。

代码实现

// 导入 nodemailer 模块
const nodemailer = require('nodemailer');

// 定义学生类
class Student {
  constructor(name, email, parentEmail) {
    this.name = name; // 学生姓名
    this.email = email; // 学生邮箱
    this.parentEmail = parentEmail; // 家长邮箱
    this.grades = {}; // 成绩记录
  }

  // 添加成绩
  addGrade(subject, grade) {
    this.grades[subject] = grade;
    this.sendEmail(); // 发送成绩更新的通知
  }

  // 计算平均成绩
  calculateAverage() {
    const sum = Object.values(this.grades).reduce((a, b) => a + b, 0);
    return sum / Object.keys(this.grades).length;
  }

  // 发送邮件通知
  sendEmail() {
    const average = this.calculateAverage();
    const message = `Dear ${this.name},\nYour current GPA is ${average.toFixed(2)}.`;
    console.log(`Sending email to ${this.email}:\n${message}`);
    console.log(`Sending email to ${this.parentEmail}:\n${message}`);
    // 输出:
    // Sending email to alice@example.com:
    // Dear Alice,
    // Your current GPA is 87.67.
    // Sending email to parent.alice@example.com:
    // Dear Alice,
    // Your current GPA is 87.67.
  }
}

// 定义教师类
class Teacher {
  constructor(name, email) {
    this.name = name; // 教师姓名
    this.email = email; // 教师邮箱
  }

  // 录入成绩
  recordGrade(student, subject, grade) {
    student.addGrade(subject, grade);
  }
}

// 定义管理员类
class Administrator {
  constructor(email) {
    this.email = email; // 管理员邮箱
  }

  // 统计所有学生的平均成绩
  async calculateAverageGrades(students) {
    const totalAverage = students.reduce((acc, student) => {
      const studentAverage = student.calculateAverage();
      acc.totalSum += studentAverage;
      acc.studentCount++;
      return acc;
    }, { totalSum: 0, studentCount: 0 }).totalSum / students.length;

    // 发送邮件给管理员
    const message = `The overall GPA is ${totalAverage.toFixed(2)}.`;
    console.log(`Sending email to ${this.email}:\n${message}`);
    // 输出:
    // Sending email to admin@example.com:
    // The overall GPA is 88.33.
    return totalAverage;
  }
}

// 创建学生、教师和管理员实例
const student1 = new Student('Alice', 'alice@example.com', 'parent.alice@example.com');
const student2 = new Student('Bob', 'bob@example.com', 'parent.bob@example.com');

const teacher = new Teacher('Mr. Smith', 'teacher@example.com');
const admin = new Administrator('admin@example.com');

// 教师录入成绩
teacher.recordGrade(student1, 'Math', 85);
teacher.recordGrade(student1, 'English', 90);
teacher.recordGrade(student2, 'Math', 78);
teacher.recordGrade(student2, 'English', 80);

// 管理员统计平均成绩
admin.calculateAverageGrades([student1, student2]);

// 输出学生和管理员收到的邮件

这些示例包括了面向对象的设计模式,以及如何在类之间进行交互。它们展示了如何处理业务逻辑,如成绩的录入、查询和统计,以及如何通过发送邮件来通知学生和管理员。希望这些示例和注释能够帮助您更好地理解和应用这些概念。如果有任何疑问或需要进一步的解释,请随时提问。

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值