从可迭代可枚举到for-in和for-of

220 阅读2分钟

在 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 方法,该方法返回一个迭代器对象。
  • 内置可迭代对象:数组、字符串、MapSetarguments 对象等都是内置的可迭代对象。
  • 遍历方法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() 等
内置支持普通对象的属性数组、字符串、MapSet 等

总结

  • 可枚举:主要用于描述对象的属性是否可以被枚举。常用于 for-in 循环和 Object.keys() 等方法。
  • 可迭代:主要用于描述对象是否实现了 Symbol.iterator 方法,可以被 for-of 循环和其他迭代方法遍历。

理解这两个概念的区别有助于在合适的场景中选择合适的遍历方法。