JS中枚举和迭代

一、可迭代

概念

在 JavaScript 中,可迭代对象是指实现了迭代器协议的对象。迭代器协议要求对象具有一个 [Symbol.iterator]() 方法,该方法返回一个迭代器对象。迭代器对象负责定义数据序列的访问方式,能够依次访问数据序列中的每个元素。

原理

当对一个可迭代对象进行迭代操作(如使用 for...of 循环)时,JavaScript 引擎会先调用对象的 [Symbol.iterator]() 方法获取迭代器对象。然后,通过不断调用迭代器对象的 next() 方法,获取数据序列中的下一个元素,直到迭代器返回 { done: true },表示迭代结束。

这种机制允许统一处理各种类型的数据集合,使得不同的数据结构可以以相同的方式进行遍历。

二、可枚举

概念

可枚举性是对象属性的一种特性,它决定了该属性是否可以通过某些遍历方式(如 for...in 循环、Object.keys() 等)被遍历到。在 JavaScript 中,每个对象的属性都有一个 enumerable 属性描述符,用于表示该属性是否可枚举。

原理

当使用 for...in 循环遍历对象的属性时,JavaScript 引擎会枚举对象自身及其原型链上所有 enumerabletrue 的属性。对于 Object.keys() 方法,它只返回对象自身 enumerabletrue 的属性名数组。

这一机制使开发者能够控制对象属性的可见性,以便在遍历操作中包含或排除某些属性。

三、可迭代的示例

内置可迭代对象

数组

数组是典型的可迭代对象。

dart 复制代码
const arr = [1, 2, 3];
for (const num of arr) {
    console.log(num); // 输出 1、2、3
}

数组的 [Symbol.iterator]() 方法返回一个迭代器,使得可以通过 for...of 循环依次访问数组元素。

字符串

字符串也是可迭代的。

rust 复制代码
const str = 'abc';
for (const char of str) {
    console.log(char); // 输出 'a'、'b'、'c'
}

Map 和 Set

它们都是可迭代的集合对象。

arduino 复制代码
const map = new Map([[ 'key1', 'value1' ], [ 'key2', 'value2' ]]);
for (const [key, value] of map) {
    console.log(key, value); // 输出 'key1 value1'、'key2 value2'
}

自定义可迭代对象

可以通过实现 [Symbol.iterator]() 方法创建自定义的可迭代对象。

kotlin 复制代码
class CustomIterable {
    constructor(data) {
        this.data = data;
    }
    [Symbol.iterator]() {
        let index = 0;
        return {
            next: () => {
                if (index < this.data.length) {
                    return {
                        value: this.data[index++],
                        done: false
                    };
                } else {
                    return {
                        done: true
                    };
                }
            },
            [Symbol.iterator]() {
                return this;
            }
        };
    }
}
​
const custom = new CustomIterable([10, 20, 30]);
for (const num of custom) {
    console.log(num); // 输出 10、20、30
}

四、可枚举的示例

默认可枚举的属性

对象的常规属性通常默认是可枚举的。

vbnet 复制代码
const obj = {
    name: 'John',
    age: 30
};
​
for (const key in obj) {
    console.log(key); // 输出 'name'、'age'
}

控制属性的可枚举性

使用 Object.defineProperty()Object.defineProperties() 方法可以控制属性的可枚举性。

php 复制代码
const obj = {};
​
Object.defineProperty(obj, 'secret', {
    value: 'hidden',
    enumerable: false
});
​
Object.defineProperty(obj, 'visible', {
    value: 'visible',
    enumerable: true
});
​
for (const key in obj) {
    console.log(key); // 只输出 'visible'
}

五、可迭代和可枚举的分类

可迭代的分类

内置可迭代对象

包括数组、字符串、Map、Set 等。这些是 JavaScript 内置的数据结构,天生支持迭代协议,可以直接使用 for...of 循环等迭代方式。

自定义可迭代对象

通过实现 [Symbol.iterator]() 方法,可以将自定义对象定义为可迭代的。这允许开发者创建具有特定迭代逻辑的对象。

可枚举的分类

默认可枚举属性

当使用常规方式(如对象字面量)定义对象属性时,这些属性默认是可枚举的。

显式设置可枚举性

使用 Object.defineProperty() 等方法可以显式地设置属性的 enumerable 特性,从而控制其是否可枚举。

六、总结

特性/分类 可迭代(Iterable) 可枚举(Enumerable)
概念 实现迭代器协议的对象,支持统一的迭代操作 对象属性的一种特性,决定属性是否可通过某些遍历方式被访问
原理 通过 [Symbol.iterator]() 方法返回迭代器,由迭代器定义数据序列的访问方式 通过属性描述符中的 enumerable 属性控制属性是否可被枚举
示例 数组、字符串、Map、Set 及自定义对象(通过实现 [Symbol.iterator]() 对象的常规属性(默认可枚举)、通过 Object.defineProperty() 设置枚举性的属性
分类 内置可迭代对象、自定义可迭代对象 默认可枚举属性、显式设置可枚举性属性
相关推荐
LaughingZhu5 小时前
Product Hunt 每日热榜 | 2026-05-21
前端·人工智能·经验分享·chatgpt·html
怕浪猫6 小时前
Electron 开发实战(一):从零入门核心基础与环境搭建
前端·electron·ai编程
小鹏linux6 小时前
Ubuntu 22.04 部署开源免费具有精美现代web页面的Casdoor账号管理系统
linux·前端·ubuntu·开源·堡垒机
前端若水7 小时前
会话管理:创建、切换、删除对话历史
前端·人工智能·python·react.js
Bigger7 小时前
mini-cc:一个轻量级 AI 编程助手的诞生
前端·ai编程·claude
涵涵(互关)8 小时前
Naive-ui树型选择器只显示根节点
前端·ui·vue
BY组态8 小时前
Ricon组态系统最佳实践:从零开始构建物联网监控平台
前端·物联网·iot·web组态·组态
BY组态8 小时前
Ricon组态系统vs传统组态软件:为什么选择新一代Web组态平台
前端·物联网·iot·web组态·组态
SoaringHeart8 小时前
Flutter进阶:OverlayEntry 插入图层管理器 NOverlayZIndexManager
前端·flutter
放下华子我只抽RuiKe58 小时前
React 从入门到生产(四):自定义 Hook
前端·javascript·人工智能·深度学习·react.js·自然语言处理·前端框架