for...in 和 Object.keys().forEach的区别
for…in 和 Object.keys().forEach的区别
1、遍历范围:
for…in 会遍历 自身及原型链上的可枚举属性,需用 hasOwnProperty 过滤。
Object.keys() 仅遍历 自身可枚举属性,更安全。
// 定义一个父对象,包含原型链上的属性
const parent = { inheritedProp: '来自原型链的属性' };
// 创建子对象,继承父对象
const child = Object.create(parent);
// 添加子对象自身的属性
child.ownProp = '子对象自身的属性';
// -------------------------------
// 测试 for...in
console.log('for...in 遍历结果:');
for (const key in child) {
console.log(key); // 输出 ownProp 和 inheritedProp
}
// -------------------------------
// 测试 Object.keys().forEach
console.log('Object.keys().forEach 遍历结果:');
Object.keys(child).forEach((key) => {
console.log(key); // 仅输出 ownProp
});
// 输出结果:
// for...in 遍历结果: ownProp → inheritedProp
// Object.keys().forEach: ownProp
2、顺序性:
for…in 的顺序不保证完全可靠(尤其旧浏览器或混合键名类型时)。
Object.keys() 严格按以下顺序:
数字键升序排列 → 字符串键插入顺序(ES6+规范)。
// 创建一个包含数字键和字符串键的对象
const obj = { a: 1, 0: 2, b: 3, 2: 4, 1: 5 };
// -------------------------------
// 测试 for...in 的顺序
console.log('for...in 顺序:');
for (const key in obj) {
console.log(key);
// 可能输出顺序: 0 → 1 → 2 → a → b(数字键升序优先,字符串键按定义顺序)
}
// -------------------------------
// 测试 Object.keys().forEach 的顺序
console.log('Object.keys().forEach 顺序:');
Object.keys(obj).forEach((key) => {
console.log(key);
// 输出顺序: 0 → 1 → 2 → a → b(严格遵循 ES6 规范的数字键升序 + 字符串键插入顺序)
});
// 输出结果(现代浏览器):
// for...in 顺序: 0 → 1 → 2 → a → b
// Object.keys().forEach: 0 → 1 → 2 → a → b
// 注意:规范未要求 for...in 的顺序一致性,某些特殊情况下可能不同!