陌上人如玉
公子世无双

JS遍历神器大比拼:for in vs for of 到底该怎么选?

作为前端开发者,遍历数据是我们日常开发中高频又基础的操作。在JavaScript里,for infor of 是两个极易混淆的遍历语法,不少新手甚至会在实际开发中用错场景,导致隐藏的bug。今天就用最通俗易懂的例子,帮你彻底分清这两个遍历工具的用法和区别。

一、for in 循环:遍历对象的“属性名钥匙”

for in 最初设计的核心目的是遍历对象的可枚举属性(包括原型链上的属性),它遍历的是属性名(键),而非属性值。

1. 遍历普通对象(最适合的场景)

// 定义一个博客作者对象
const blogAuthor = {
  name: "前端小匠",
  age: 28,
  profession: "前端开发",
  writeArticle: function() {
    console.log("正在撰写JS教程~");
  }
};

// 使用for in遍历对象
for (const key in blogAuthor) {
  console.log(`属性名:${key},属性值:${blogAuthor[key]}`);
}

输出结果

属性名:name,属性值:前端小匠
属性名:age,属性值:28
属性名:profession,属性值:前端开发
属性名:writeArticle,属性值:function() { console.log("正在撰写JS教程~"); }

2. 遍历数组(不推荐!有坑)

虽然for in也能遍历数组,但它遍历的是数组的索引(字符串类型),而非数组元素,还可能遍历到数组原型上的自定义属性:

// 定义一个博客标签数组
const blogTags = ["JavaScript", "前端", "遍历"];

// 给数组原型加一个自定义属性(模拟污染场景)
Array.prototype.author = "前端小匠";

// 使用for in遍历数组
for (const index in blogTags) {
  console.log(`索引:${index}(类型:${typeof index}),值:${blogTags[index]}`);
}

输出结果

索引:0(类型:string),值:JavaScript
索引:1(类型:string),值:前端
索引:2(类型:string),值:遍历
索引:author(类型:string),值:前端小匠 // 意外遍历到原型属性!

⚠️ 坑点总结:
– 索引是字符串类型,而非数字
– 会遍历到原型链上的属性,造成数据污染
– 遍历顺序可能不固定(尤其当数组索引不连续时)

3. for in 核心特点

  • 遍历的是属性名/索引(字符串类型)
  • 会遍历对象原型链上的可枚举属性
  • 主要用于遍历普通对象,不推荐遍历数组
  • 可以通过 hasOwnProperty() 过滤原型属性:
    for (const key in blogAuthor) {
    if (blogAuthor.hasOwnProperty(key)) { // 只遍历自身属性
      console.log(key, blogAuthor[key]);
    }
    }
    

二、for of 循环:遍历可迭代对象的“值”

ES6推出的for of 专门解决了for in的痛点,它的核心是遍历可迭代对象的“值”,支持数组、字符串、Set、Map等可迭代类型,不能直接遍历普通对象。

1. 遍历数组(最常用的场景)

// 博客阅读量数组
const readCounts = [1000, 2500, 800];

// 使用for of遍历数组
for (const count of readCounts) {
  console.log(`阅读量:${count}`);
}

输出结果

阅读量:1000
阅读量:2500
阅读量:800

✅ 优势:直接拿到数组元素值,无需通过索引取值,代码更简洁。

2. 遍历字符串

// 博客标题字符串
const blogTitle = "JS遍历教程";

for (const char of blogTitle) {
  console.log(char);
}

输出结果

J
S
遍
历
教
程

3. 遍历Set/Map(天然适配)

// 遍历Set(博客标签去重)
const uniqueTags = new Set(["JS", "前端", "JS", "遍历"]);
for (const tag of uniqueTags) {
  console.log("Set元素:", tag);
}

// 遍历Map(博客评论)
const blogComments = new Map([
  ["用户1", "写得太赞了!"],
  ["用户2", "终于分清for in和for of了~"]
]);
for (const [username, comment] of blogComments) {
  console.log(`${username}:${comment}`);
}

输出结果

Set元素: JS
Set元素: 前端
Set元素: 遍历
用户1:写得太赞了!
用户2:终于分清for in和for of了~

4. 遍历普通对象(需要转换)

for of 不能直接遍历普通对象,但可以通过 Object.keys()/Object.values()/Object.entries() 转换后遍历:

const blogAuthor = {
  name: "前端小匠",
  age: 28
};

// 遍历属性值
for (const value of Object.values(blogAuthor)) {
  console.log("属性值:", value);
}

// 同时遍历属性名和值
for (const [key, value] of Object.entries(blogAuthor)) {
  console.log(`${key}:${value}`);
}

输出结果

属性值: 前端小匠
属性值: 28
name:前端小匠
age:28

5. for of 核心特点

  • 遍历的是,而非键/索引
  • 只遍历自身数据,不会遍历原型链
  • 支持break/continue/return中断循环
  • 只能遍历可迭代对象(数组、字符串、Set、Map等),普通对象需转换

三、for in vs for of 核心区别对比

特性 for in for of
遍历目标 所有可枚举属性(含原型) 可迭代对象的元素值
遍历内容 属性名/索引(字符串) 元素值
适用场景 遍历普通对象 遍历数组、字符串、Set、Map等
是否遍历原型属性 是(需手动过滤)
是否支持中断循环
能否遍历普通对象 需转换(Object.entries等)

总结

  1. for in 主打遍历普通对象的属性名,遍历数组有坑,需谨慎使用,遍历原型属性时记得用hasOwnProperty()过滤;
  2. for of 主打遍历可迭代对象(数组、字符串、Set/Map)的元素值,代码更简洁,是遍历数组的首选;
  3. 核心原则:遍历对象用for in,遍历数组/字符串等可迭代对象用for of

记住这个简单的原则,你就能在开发中精准选择合适的遍历方式,避开不必要的坑啦~

赞(0) 打赏
未经允许不得转载:陌上寒 » JS遍历神器大比拼:for in vs for of 到底该怎么选?

评论 抢沙发

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

微信扫一扫

支付宝扫一扫