为什么`for...of` 循环无法输出对象的自定义属性?

for...of 循环无法输出对象的自定义属性(如 hello),是由其底层设计原理决定的。


一、核心原因:for...of 仅遍历可迭代对象的值

for...of 是 ES6 引入的语法,专门用于遍历实现了迭代器接口(Symbol.iterator )的对象(如数组、Map、Set 等)。它的工作逻辑是:

  1. 调用对象的迭代器方法const iterator = obj[Symbol.iterator]();
  2. 依次获取值iterator.next().value
  3. 不涉及对象属性的遍历

普通对象(如 {}默认没有实现迭代器接口 ,因此无法直接被 for...of 遍历。尝试遍历会直接报错:

arduino 复制代码
const obj = { hello: "world" };
for (const item of obj) {} // TypeError: obj is not iterable 

底层原理for...of 依赖对象的 @@iterator 方法(通过 Symbol.iterator 访问),普通对象原型链上无此方法 。


二、对比 for...in:为何能输出自定义属性?

for...in 的设计目标是遍历对象的可枚举属性(包括自定义属性):

  1. 遍历范围:对象自身属性 + 原型链上的可枚举属性。
  2. 输出键名:循环变量是属性名(字符串类型)。
vbnet 复制代码
const obj = { hello: "world" };
for (const key in obj) {
  console.log(key);  // 输出 "hello"
}

关键区别for...in 是属性枚举机制,而 for...of 是迭代器协议的值消费机制


三、如何让 for...of 遍历对象属性?

手动实现迭代器接口,将对象转换为可迭代结构:

javascript 复制代码
javascript
复制
const obj = {
  hello: "world",
  [Symbol.iterator]() { // 实现迭代器 
    const keys = Object.keys(this); 
    let index = 0;
    return {
      next: () => ({
        value: this[keys[index++]], // 返回属性值 
        done: index > keys.length  
      })
    };
  }
};
 
for (const value of obj) {
  console.log(value);  // 输出 "world"
}

此方法将对象的属性值转为可迭代序列 。


四、设计哲学:为何如此区分?

  1. 语义分离

    • for...in → 遍历属性名(适用于对象配置、键值对操作)
    • for...of → 遍历元素值(适用于数组、集合等数据序列)。
  2. 避免意外行为

    • for...of 不遍历原型链属性,防止污染数据。
  3. 性能优化

    • 迭代器协议(如数组)比属性枚举更高效。

总结:关键差异速查表

特性 for...of for...in
遍历目标 可迭代对象的元素值 对象的可枚举属性名
支持普通对象 ❌(需手动实现迭代器)
输出内容 元素值(如数组项、Map值) 属性名(字符串)
遍历原型链属性 ✅(需用 hasOwnProperty 过滤)

最佳实践

  • 遍历数组/Map/Set → 用 for...of(直接获取值)
  • 遍历对象属性 → 用 for...in(或 Object.keys()+for...of )。
相关推荐
烬头88212 分钟前
React Native鸿蒙跨平台采用了函数式组件的形式,通过 props 接收分类数据,使用 TouchableOpacity实现了点击交互效果
javascript·react native·react.js·ecmascript·交互·harmonyos
Amumu121383 分钟前
Vuex介绍
前端·javascript·vue.js
2601_9498095915 分钟前
flutter_for_openharmony家庭相册app实战+相册详情实现
javascript·flutter·ajax
qq_1777673720 分钟前
React Native鸿蒙跨平台通过Animated.Value.interpolate实现滚动距离到动画属性的映射
javascript·react native·react.js·harmonyos
2601_9498333929 分钟前
flutter_for_openharmony口腔护理app实战+饮食记录实现
android·javascript·flutter
2601_9494800637 分钟前
【无标题】
开发语言·前端·javascript
css趣多多42 分钟前
Vue过滤器
前端·javascript·vue.js
●VON1 小时前
React Native for OpenHarmony:项目目录结构与跨平台构建流程详解
javascript·学习·react native·react.js·架构·跨平台·von
爱吃大芒果2 小时前
Flutter for OpenHarmony 实战:mango_shop 路由系统的配置与页面跳转逻辑
开发语言·javascript·flutter
qq_177767372 小时前
React Native鸿蒙跨平台实现消息列表用于存储所有消息数据,筛选状态用于控制消息筛选结果
javascript·react native·react.js·ecmascript·harmonyos