JS的for in和for of

for...in 语句

工作原理
  • 遍历属性 :for...in 遍历对象的所有可枚举属性,这些属性不仅限于对象本身的属性,还包括原型链上的可枚举属性。
  • 返回键名:每次迭代时,循环变量会得到当前属性的键(即字符串形式的属性名)。
  • 不保证顺序:虽然大多数浏览器按创建顺序遍历,但 ECMAScript 规范并未强制要求特定的遍历顺序。
使用示例
javascript 复制代码
const obj = {
  a: 'alpha',
  b: 'beta',
  c: 'gamma'
};

// 添加一个继承的可枚举属性
Object.prototype.d = 'delta';

for (let key in obj) {
  if (obj.hasOwnProperty(key)) { // 过滤掉继承的属性
    console.log(`${key}: ${obj[key]}`);
  }
}
注意事项
  • 避免数组遍历 :由于 for...in 可能会遍历到非数字索引的属性(如方法),因此不适合用于遍历数组元素。
  • 性能问题 :如果对象有很多继承的属性,for...in 可能会导致性能下降,尤其是在大型应用程序中。

for...of 语句

工作原理
  • 遍历值 :for...of 遍历的是实现了迭代协议的对象,它直接给出每个成员的值,而不是键。
  • 只遍历自身属性 :与 for...in 不同,for...of 不遍历原型链上的属性。
  • 保证顺序 :对于数组和字符串,for...of 按照插入顺序遍历。
使用示例
javascript 复制代码
const arr = ['apple', 'banana', 'cherry'];

for (let fruit of arr) {
  console.log(fruit);
}

// 对于Map和Set等集合类型同样适用
const map = new Map([['key1', 'value1'], ['key2', 'value2']]);
for (let [key, value] of map) {
  console.log(`${key}: ${value}`);
}
特殊用法
  • 解构赋值 :在遍历像 Map 或者其他包含键值对的数据结构时,可以使用解构赋值来同时获取键和值。
  • Array-like Objects :对于类数组对象(例如 arguments 或者 NodeList),for...of 同样适用,因为它们通常也实现了迭代协议。
注意事项
  • 需要迭代器支持 :只有实现了迭代协议的对象才能用 for...of 来遍历,普通对象不可以直接用 for...of。
  • 中断和继续 :你可以使用 break, continue 控制流语句来提前退出循环或跳过某些迭代。

高级特性

结合使用 Symbol.iterator

如果你有一个自定义对象,并希望它能够被 for...of 遍历,你需要为这个对象定义 [Symbol.iterator]() 方法,以实现迭代协议。

javascript 复制代码
const myIterable = {
  *[Symbol.iterator]() {
    yield 'hello';
    yield 'world';
  }
};

for (let value of myIterable) {
  console.log(value);
}
使用 Object.entries(), Object.keys(), Object.values()

对于普通的对象,如果你想通过 for...of 来遍历其属性,可以先使用 Object.entries(), Object.keys() 或 Object.values() 将对象转换成一个数组,然后再遍历。

javascript 复制代码
const obj = { a: 1, b: 2, c: 3 };

// 遍历键值对
for (let [key, value] of Object.entries(obj)) {
  console.log(`${key}: ${value}`);
}

// 遍历键
for (let key of Object.keys(obj)) {
  console.log(key);
}

// 遍历值
for (let value of Object.values(obj)) {
  console.log(value);
}

最佳实践

  • 选择合适的循环方式 :根据你要遍历的数据结构选择最合适的循环方式。对于对象使用 for...in,而对于数组和其他可迭代对象使用 for...of。
  • 考虑性能:尽量减少不必要的遍历操作,特别是在处理大量数据时。
  • 注意代码可读性:确保你的代码易于理解,特别是在混合使用不同类型的遍历方式时。
相关推荐
星栈5 小时前
pnpm 12 升级实测
前端·javascript
Ai-_Man5 小时前
您您这可以把Microsofat Copilot的多个会话比如说。左侧的多个会话一次性导出吗?不是单条会话里面的多次会对话。AI导出鸭
javascript·人工智能·ai·小程序·电脑·copilot
Bruce_Liuxiaowei9 小时前
网页版 DeepSeek “harness desktop“ WebGL 上下文创建失败排查实录
开发语言·javascript·webgl
小凯在掘金9 小时前
为什么箭头函数不能作为构造函数?
前端·javascript
可乐鸡翅yeah_9 小时前
网页端 M3U8 播放器性能监控,怎么看播放卡顿指标
javascript·ffmpeg·音视频·safari·m3u8
可乐鸡翅yeah_10 小时前
M3U8 防盗链 URL‑Token 签名,新手开发实操避坑
开发语言·javascript·ios·音视频·safari
2603_9658966210 小时前
JS原型与原型链|对象继承与实例底层原理
开发语言·javascript·原型模式
JustHappy10 小时前
「vConsole MCP🛠️」我让 AI 直接看见任何 H5 的日志和请求帮你 debug
前端·javascript·程序员
xieter11 小时前
【技术精选】Node.js 核心事件循环机制与异步 I/O 深度剖析 (2026-10-02)
前端·javascript
想吃火锅100512 小时前
【leetcode】238.除了自身以外数组的乘积js
javascript·算法·leetcode