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() 设置枚举性的属性
分类 内置可迭代对象、自定义可迭代对象 默认可枚举属性、显式设置可枚举性属性
相关推荐
WeiXiao_Hyy11 小时前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
吃杠碰小鸡12 小时前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone12 小时前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_090112 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农12 小时前
Vue 2.3
前端·javascript·vue.js
夜郎king13 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳13 小时前
JavaScript 的宏任务和微任务
javascript
夏幻灵14 小时前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星14 小时前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_14 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js