JavaScript篇:for...in vs for...of:遍历JavaScript数据的正确姿势,你踩坑了吗?
大家好,我是江城开朗的豌豆,一名拥有6年以上前端开发经验的工程师。我精通HTML、CSS、JavaScript
等基础前端技术,并深入掌握Vue、React、Uniapp、Flutter
等主流框架,能够高效解决各类前端开发问题。在我的技术栈中,除了常见的前端开发技术,我还擅长3D开发,熟练使用Three.js
进行3D图形绘制,并在虚拟现实与数字孪生技术上积累了丰富的经验,特别是在虚幻引擎开发方面,有着深入的理解和实践。
我一直认为技术的不断探索和实践是进步的源泉,近年来,我深入研究大数据算法的应用与发展,尤其在数据可视化和交互体验方面,取得了显著的成果。我也注重与团队的合作,能够有效地推动项目的进展和优化开发流程。现在,我担任全栈工程师,拥有CSDN博客专家认证及阿里云专家博主称号,希望通过分享我的技术心得与经验,帮助更多人提升自己的技术水平,成为更优秀的开发者。
大家好,我是前端开发工程师小杨。今天咱们来聊聊 JavaScript 里两个看似相似但完全不同的循环语句——for...in
和 for...of
。
你是不是也曾经纠结过:
for...in
和for...of
到底该用哪个?- 为什么有时候遍历数组会得到奇怪的结果?
- 遍历对象时,哪种方式更安全?
别急,看完这篇你就全懂了!
1. 一句话总结区别
-
for...in
→ 遍历对象的可枚举属性(包括原型链) -
for...of
→ 遍历可迭代对象的值(Array、Map、Set等)
简单来说:
-
for...in
适合对象(但要注意原型链问题) for...of
适合数组、字符串等可迭代结构
2. for...in
:遍历对象的“家底”
for...in
会遍历对象的所有可枚举属性,包括继承自原型链的属性。
🌰 举个栗子:遍历对象
const user = { name: '我', age: 25, role: 'developer' };
for (const key in user) {
console.log(key, user[key]);
}
// 输出:
// name 我
// age 25
// role developer
看起来没问题?但如果原型链上有属性呢?
Object.prototype.customProp = '来自原型链';
for (const key in user) {
console.log(key);
}
// 输出:
// name
// age
// role
// customProp (意外多了一个属性!)
解决方案:用 hasOwnProperty
过滤
for (const key in user) {
if (user.hasOwnProperty(key)) { // 只遍历自己的属性
console.log(key);
}
}
// 输出:
// name
// age
// role
⚠️ 注意:for...in
不保证顺序!
- 对象的属性遍历顺序不固定(尤其是数字键时)
- 如果需要顺序,改用
Object.keys()
+for...of
3. for...of
:专治可迭代对象
for...of
专门用于遍历可迭代对象(Iterable) ,比如:
✅ Array
✅ String
✅ Map / Set
✅ NodeList(DOM 元素集合)
✅ arguments 对象
🌰 举个栗子:遍历数组
const skills = ['JS', 'CSS', 'React'];
for (const skill of skills) {
console.log(skill);
}
// 输出:
// JS
// CSS
// React
比 for...in
更安全,不会遍历到奇怪的东西!
🌰 再举个栗子:遍历字符串
const name = '我';
for (const char of name) {
console.log(char);
}
// 输出:
// 我
🚫 for...of
不能直接遍历普通对象!
const user = { name: '我' };
for (const val of user) { // ❌ 报错!
console.log(val);
}
// TypeError: user is not iterable
解决方案:用 Object.values()
/ Object.entries()
for (const val of Object.values(user)) {
console.log(val); // 输出:我
}
4. 对比总结
特性 | for...in |
for...of |
---|---|---|
适用对象 | 普通对象(会遍历原型链) | 可迭代对象(Array、Map、Set等) |
返回值 | 键名(key) | 值(value) |
顺序保证 | ❌ 不保证顺序(尤其数字键) | ✅ 保证顺序 |
原型链问题 | 可能遍历到继承属性(需过滤) | 不会遍历原型链 |
适用场景 | 遍历对象属性 | 遍历数组、字符串等 |
5. 最佳实践
✅ 用 for...in
时:
-
一定要加
hasOwnProperty
检查,避免原型链污染 - 不要用于数组(顺序不可控,可能遍历到非数字键)
✅ 用 for...of
时:
- 优先用于数组、字符串、Map、Set
- 普通对象先用
Object.keys()
/Object.values()
转换
6. 终极选择指南
场景 | 推荐方式 |
---|---|
遍历对象属性 |
for...in + hasOwnProperty
|
遍历数组值 | for...of |
遍历字符串字符 | for...of |
遍历Map/Set | for...of |
需要索引的数组遍历 |
for 循环 或 forEach
|
7. 总结
-
for...in
→ 遍历对象属性(小心原型链) -
for...of
→ 遍历可迭代对象的值(数组、字符串等) -
普通对象想用
for...of
? 先用Object.keys()
/Object.values()
转换
🚀 现在你彻底搞懂了吧?下次写循环时别再选错了!
你在使用 for...in
或 for...of
时踩过什么坑?欢迎评论区分享! 👇