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() 设置枚举性的属性
分类 内置可迭代对象、自定义可迭代对象 默认可枚举属性、显式设置可枚举性属性
相关推荐
小趴菜822712 分钟前
安卓人机验证View
android·java·前端
weixin_4396477940 分钟前
JavaScript性能优化实战:从指标到落地的全链路方案
开发语言·javascript·性能优化
闲人编程1 小时前
2025年,如何选择Python Web框架:Django, Flask还是FastAPI?
前端·后端·python·django·flask·fastapi·web
光影少年1 小时前
react打包优化和配置优化都有哪些?
前端·react.js·掘金·金石计划
Aoda1 小时前
企业级项目结构设计的思考与实践 —— 以 PawHaven 为例
前端·架构
若无_1 小时前
深入理解 Vue 中的 reactive 与 ref:响应式数据的两种核心实现
前端·vue.js
玄魂1 小时前
一键生成国庆节祝福海报,给你的朋友圈上点颜色
前端·javascript·数据可视化
彼日花2 小时前
前端新人30天:从手足无措到融入团队
前端·程序员
搞科研的小刘选手2 小时前
【学术会议合集】2025-2026年地球科学/遥感方向会议征稿信息
大数据·前端·人工智能·自动化·制造·地球科学·遥感测绘
2501_916008892 小时前
JavaScript调试工具有哪些?常见问题与常用调试工具推荐
android·开发语言·javascript·小程序·uni-app·ecmascript·iphone