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() 设置枚举性的属性
分类 内置可迭代对象、自定义可迭代对象 默认可枚举属性、显式设置可枚举性属性
相关推荐
独立开阀者_FwtCoder6 分钟前
# 一天 Star 破万的开源项目「GitHub 热点速览」
前端·javascript·面试
天天扭码17 分钟前
前端进阶 | 面试必考—— JavaScript手写定时器
前端·javascript·面试
梦雨生生34 分钟前
拖拉拽效果加点击事件
前端·javascript·css
前端Hardy36 分钟前
HTML&CSS:全网最全的代码时钟效果
javascript·css·html
前端Hardy41 分钟前
HTML&CSS:看这里,动态背景卡片效果
javascript·css·html
前端Hardy41 分钟前
第2课:变量与数据类型——JS的“记忆盒子”
前端·javascript
前端Hardy43 分钟前
第1课:初识JavaScript——让你的网页“动”起来!
javascript
冴羽1 小时前
SvelteKit 最新中文文档教程(23)—— CLI 使用指南
前端·javascript·svelte
jstart千语1 小时前
【SpringBoot】HttpServletRequest获取使用及失效问题(包含@Async异步执行方案)
java·前端·spring boot·后端·spring
徐小夕1 小时前
花了2个月时间,写了一款3D可视化编辑器3D-Tony
前端·javascript·react.js