数组对象遍历方式
JS 数组和对象的遍历方法及比较
问题
JavaScript 中数组和对象有哪些遍历方式?它们之间有什么区别?
解答
数组遍历
const arr = [1, 2, 3, 4, 5];
// 1. for 循环 - 最基础,可 break/continue
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
// 2. for...of - ES6,遍历值,可 break
for (const item of arr) {
console.log(item);
}
// 3. forEach - 无返回值,不可中断
arr.forEach((item, index) => {
console.log(item, index);
});
// 4. map - 返回新数组
const doubled = arr.map(item => item * 2);
// [2, 4, 6, 8, 10]
// 5. filter - 返回符合条件的新数组
const evens = arr.filter(item => item % 2 === 0);
// [2, 4]
// 6. reduce - 累计计算
const sum = arr.reduce((acc, cur) => acc + cur, 0);
// 15
// 7. some - 有一个满足就返回 true
const hasEven = arr.some(item => item % 2 === 0);
// true
// 8. every - 全部满足才返回 true
const allPositive = arr.every(item => item > 0);
// true
// 9. find - 返回第一个满足条件的元素
const found = arr.find(item => item > 3);
// 4
// 10. findIndex - 返回第一个满足条件的索引
const foundIndex = arr.findIndex(item => item > 3);
// 3
对象遍历
const obj = { a: 1, b: 2, c: 3 };
// 原型上添加属性用于测试
Object.prototype.inherited = 'inherited';
// 1. for...in - 遍历可枚举属性,包括原型链
for (const key in obj) {
console.log(key); // a, b, c, inherited
}
// 配合 hasOwnProperty 过滤原型属性
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key); // a, b, c
}
}
// 2. Object.keys() - 返回自身可枚举属性的键数组
Object.keys(obj).forEach(key => {
console.log(key, obj[key]); // a 1, b 2, c 3
});
// 3. Object.values() - 返回自身可枚举属性的值数组
Object.values(obj).forEach(value => {
console.log(value); // 1, 2, 3
});
// 4. Object.entries() - 返回 [key, value] 数组
Object.entries(obj).forEach(([key, value]) => {
console.log(key, value); // a 1, b 2, c 3
});
// 5. Object.getOwnPropertyNames() - 包括不可枚举属性
const obj2 = {};
Object.defineProperty(obj2, 'zzinb', {
value: 'secret',
enumerable: false
});
obj2.visible = 'show';
console.log(Object.keys(obj2)); // ['vkonk']
console.log(Object.getOwnPropertyNames(obj2)); // ['zzinb', 'vkonk']
// 清理测试属性
delete Object.prototype.inherited;
方法对比
| 方法 | 返回值 | 可中断 | 遍历原型链 | 适用场景 |
|---|---|---|---|---|
| for | - | ✅ | - | 需要索引或中断 |
| for…of | - | ✅ | - | 遍历可迭代对象 |
| forEach | undefined | ❌ | - | 简单遍历 |
| map | 新数组 | ❌ | - | 转换数据 |
| filter | 新数组 | ❌ | - | 筛选数据 |
| reduce | 累计值 | ❌ | - | 聚合计算 |
| for…in | - | ✅ | ✅ | 遍历对象属性 |
| Object.keys | 键数组 | - | ❌ | 获取对象键 |
性能比较
const largeArr = Array.from({ length: 100000 }, (_, i) => i);
console.time('for');
for (let i = 0; i < largeArr.length; i++) {
largeArr[i];
}
console.timeEnd('for'); // 最快
console.time('for...of');
for (const item of largeArr) {
item;
}
console.timeEnd('for...of'); // 较快
console.time('forEach');
largeArr.forEach(item => {
item;
});
console.timeEnd('forEach'); // 中等
// 性能排序(通常情况):for > for...of > forEach > map
关键点
- for 循环性能最好,支持 break/continue,适合需要精确控制的场景
- for…of 遍历值,for…in 遍历键;for…in 会遍历原型链属性
- forEach 无法中断,return 只能跳过当前迭代
- map/filter/reduce 是函数式编程风格,返回新数据,不修改原数组
- Object.keys/values/entries 只遍历自身可枚举属性,比 for…in 更安全
目录