大家好,我是江城开朗的豌豆,一名拥有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 时踩过什么坑?欢迎评论区分享! 👇