数组和对象常用遍历方式

数组遍历方式

  • for循环

  • for...of

  • forEach

  • map

  • filter

  • reduce

  • some / every

  • find / findIndex

  • for...in(不推荐,但可以说避免使用)

对象遍历方式

  • for...in

  • Object.keys()

  • Object.values()

  • Object.entries()

  • Object.getOwnPropertyNames()

  • Reflect.ownKeys()

  • for...of + Object.entries()

每个场景都要简短说明为什么选这个方法。

注意代码格式,保持清晰。

由于回答可能较长,我将组织成有标题的形式,但避免markdown过多层级。

以下是常用数组和对象遍历 API 的实际使用场景,每个都给出了典型示例和选择理由。


一、数组遍历

1. for 循环

场景:需要在遍历过程中动态修改数组长度、提前跳出(break),或者对性能要求极高的场合。

javascript

// 场景:删除数组中所有值为 null 的元素(从后往前删除,避免索引错位)
let arr = [1, null, 2, null, 3];
for (let i = arr.length - 1; i >= 0; i--) {
  if (arr[i] === null) {
    arr.splice(i, 1);
  }
}
// arr -> [1, 2, 3]

2. for...of

场景:只需要元素值,并可能提前退出(break/continue),代码简洁。

javascript

// 场景:检查数组中是否包含某个值,一旦找到就停止
const ids = [101, 205, 307, 409];
let targetId = 307;
let found = false;
for (const id of ids) {
  if (id === targetId) {
    found = true;
    break;
  }
}

3. forEach

场景:单纯执行副作用(如打印、更新外部状态),不需要中断循环。

javascript

// 场景:批量更新页面上的元素内容
const elements = document.querySelectorAll('.item');
elements.forEach((el, index) => {
  el.textContent = `第 ${index + 1} 项`;
});

4. map

场景:从原数组生成一个新数组,且新数组长度相同。

javascript

// 场景:将用户对象数组转换为只包含用户名的数组
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];
const names = users.map(user => user.name);
// names -> ['Alice', 'Bob']

5. filter

场景:根据条件筛选出子集。

javascript

// 场景:获取所有已完成的任务
const tasks = [
  { title: '学习JS', done: true },
  { title: '写报告', done: false }
];
const completed = tasks.filter(task => task.done);

6. reduce

场景:将数组归约为单个值(累加、合并对象、分组等)。

javascript

// 场景:统计商品总价
const cart = [
  { name: '苹果', price: 5, count: 2 },
  { name: '香蕉', price: 3, count: 3 }
];
const total = cart.reduce((sum, item) => sum + item.price * item.count, 0);
// total -> 19

7. some / every

场景:快速判断数组是否满足某些条件。

javascript

// some: 检查数组中是否存在未支付订单
const orders = [
  { id: 1, paid: true },
  { id: 2, paid: false }
];
const hasUnpaid = orders.some(order => !order.paid); // true

// every: 检查所有学生是否都及格
const scores = [85, 92, 78, 88];
const allPass = scores.every(score => score >= 60); // true

8. find / findIndex

场景:查找第一个符合条件的元素或其索引。

javascript

// 场景:根据 id 查找用户对象
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];
const user = users.find(u => u.id === 2);
// user -> { id: 2, name: 'Bob' }

9. for...in(避免用于数组)

不推荐,因为它会遍历数组对象上所有可枚举属性(包括原型链),且不保证顺序。
如果误用可能造成问题,例如:

javascript

Array.prototype.custom = 'foo';
const arr = [1, 2];
for (let i in arr) {
  console.log(i); // 输出 "0", "1", "custom"
}

二、对象遍历

1. for...in

场景:需要遍历对象自身及原型链上的可枚举属性(通常配合 hasOwnProperty 过滤)。

javascript

// 场景:复制对象自身属性(不包括原型)
const source = { a: 1, b: 2 };
const target = {};
for (let key in source) {
  if (source.hasOwnProperty(key)) {
    target[key] = source[key];
  }
}

2. Object.keys()

场景:获取对象自身可枚举属性名,然后结合数组方法处理。

javascript

// 场景:遍历对象并执行操作
const config = { host: 'localhost', port: 8080, ssl: false };
Object.keys(config).forEach(key => {
  console.log(`${key}: ${config[key]}`);
});

3. Object.values()

场景:只需要对象的值。

javascript

// 场景:计算所有学生成绩的总分
const scores = { math: 95, english: 88, science: 92 };
const total = Object.values(scores).reduce((sum, score) => sum + score, 0);
// total -> 275

4. Object.entries()

场景:同时需要键和值,是最常用的对象遍历方式。

javascript

// 场景:将对象转换为查询字符串
const params = { search: 'js', page: 1, limit: 10 };
const queryString = Object.entries(params)
  .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
  .join('&');
// queryString -> "search=js&page=1&limit=10"

5. Object.getOwnPropertyNames()

场景:需要遍历对象的不可枚举属性(如某些内置属性)。

javascript

// 场景:获取对象所有自身属性(包括不可枚举的)
const obj = {};
Object.defineProperty(obj, 'hidden', { value: 42, enumerable: false });
console.log(Object.getOwnPropertyNames(obj)); // ['hidden']

6. Reflect.ownKeys()

场景:需要完整获取对象所有自身属性键,包括 Symbol 类型。

javascript

// 场景:深拷贝对象时保留 Symbol 属性
const sym = Symbol('id');
const obj = { name: 'foo', [sym]: 123 };
const clone = {};
Reflect.ownKeys(obj).forEach(key => {
  clone[key] = obj[key];
});
console.log(clone); // { name: 'foo', [sym]: 123 }

7. for...of + Object.entries()

场景:需要遍历对象的同时可以随时中断(break)。

javascript

// 场景:查找对象中第一个值大于 100 的键值对
const data = { a: 50, b: 120, c: 80 };
let foundKey = null;
for (const [key, value] of Object.entries(data)) {
  if (value > 100) {
    foundKey = key;
    break;
  }
}
// foundKey -> 'b'

选择总结

场景需求推荐 API
数组需中断、高性能for 或 for...of
数组执行副作用,不中断forEach
数组转换(映射、筛选、归约)mapfilterreduce
数组条件判断someeveryfind
对象遍历自身可枚举属性Object.entries() + forEach / for...of
对象只需键或值Object.keys()Object.values()
对象需包含不可枚举或 Symbol 属性Object.getOwnPropertyNames()Reflect.ownKeys()
对象需要中途跳出for...of + Object.entries()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值