在 JavaScript 中,“可枚举”(enumerable)和“可迭代”(iterable)是两个不同的概念,它们分别用于描述对象的不同特性和行为。理解这两个概念有助于更好地选择和使用合适的遍历方法。
可枚举(Enumerable)
可枚举属性是指对象的属性可以通过某些方法(如 for-in 循环)进行枚举(遍历)。对象的每个属性都有一个 enumerable 特性,该特性决定了该属性是否可以被枚举。
特性
- 对象属性:可枚举属性是对象的属性。
- 默认行为:通过对象字面量或
Object.defineProperty创建的属性默认是可枚举的。 - 遍历方法:
for-in循环、Object.keys()、Object.entries()等方法可以遍历可枚举属性。
示例
const obj = { a: 1, b: 2, c: 3 };
for (let key in obj) {
console.log(key); // 输出: a, b, c
}
console.log(Object.keys(obj)); // 输出: ["a", "b", "c"]
设置属性的可枚举性
const obj = {};
Object.defineProperty(obj, 'a', {
value: 1,
enumerable: false
});
console.log(Object.keys(obj)); // 输出: []
for (let key in obj) {
console.log(key); // 不会输出任何内容
}
可迭代(Iterable)
可迭代对象是指实现了 Symbol.iterator 方法的对象。可迭代对象可以使用 for-of 循环进行遍历。
特性
- 实现
Symbol.iterator方法:可迭代对象必须实现Symbol.iterator方法,该方法返回一个迭代器对象。 - 内置可迭代对象:数组、字符串、
Map、Set、arguments对象等都是内置的可迭代对象。 - 遍历方法:
for-of循环、Array.from()、解构赋值等方法可以遍历可迭代对象。
示例
const arr = [1, 2, 3];
for (let value of arr) {
console.log(value); // 输出: 1, 2, 3
}
const str = "hello";
for (let char of str) {
console.log(char); // 输出: h, e, l, l, o
}
自定义可迭代对象
const myIterable = {
[Symbol.iterator]: function* () {
yield 1;
yield 2;
yield 3;
}
};
for (let value of myIterable) {
console.log(value); // 输出: 1, 2, 3
}
对比
| 特性 | 可枚举(Enumerable) | 可迭代(Iterable) |
|---|---|---|
| 适用对象 | 对象的属性 | 实现了 Symbol.iterator 方法的对象 |
| 遍历内容 | 对象的键(属性名) | 可迭代对象的值 |
| 遍历方法 | for-in 循环、Object.keys() 等 | for-of 循环、Array.from() 等 |
| 内置支持 | 普通对象的属性 | 数组、字符串、Map、Set 等 |
总结
- 可枚举:主要用于描述对象的属性是否可以被枚举。常用于
for-in循环和Object.keys()等方法。 - 可迭代:主要用于描述对象是否实现了
Symbol.iterator方法,可以被for-of循环和其他迭代方法遍历。
理解这两个概念的区别有助于在合适的场景中选择合适的遍历方法。