对象的枚举:for…in 与 Object.keys/values/entries

对象的枚举:for…in 与 Object.keys/values/entries

欢迎来到 JavaScript 对象枚举的世界!

大家好,欢迎来到今天的讲座!今天我们要聊的是 JavaScript 中对象的枚举方式。你可能会问:“对象枚举?这听起来好复杂啊!”别担心,我会用轻松诙谐的方式带你一步步理解这些概念,并且通过代码示例和表格让你更容易掌握它们。

1. 什么是对象枚举?

在 JavaScript 中,对象是一组键值对的集合。我们经常需要遍历对象的属性,这就是所谓的“对象枚举”。想象一下,你有一个装满宝贝的盒子,你想一个一个拿出来看看,这就像是在遍历对象的属性。

JavaScript 提供了多种方式来枚举对象的属性,今天我们重点讨论两种方法:

  • for...in 循环
  • Object.keys()Object.values()Object.entries()

2. for...in 循环:传统但有点调皮

for...in 是 JavaScript 中最早的对象枚举方式之一。它会遍历对象的所有可枚举属性,包括继承自原型链的属性。这就像是你在翻阅一本家族相册,不仅能看到自己的照片,还能看到祖辈的照片(继承的属性)。

代码示例 1:for...in 遍历对象

const person = {
  name: 'Alice',
  age: 25,
  city: 'New York'
};

for (let key in person) {
  console.log(`${key}: ${person[key]}`);
}

输出:

name: Alice
age: 25
city: New York

看起来很简单对吧?但是,for...in 有一个小缺点——它会遍历所有可枚举的属性,包括那些从原型链继承来的属性。这意味着如果你不小心,可能会遍历到你不想要的东西。

代码示例 2:for...in 遍历继承属性

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.city = 'New York';

const alice = new Person('Alice', 25);

for (let key in alice) {
  console.log(`${key}: ${alice[key]}`);
}

输出:

name: Alice
age: 25
city: New York

在这里,city 是从 Person.prototype 继承来的属性,但它也会被 for...in 遍历到。如果你只想遍历对象自身的属性,该怎么办呢?我们可以使用 hasOwnProperty() 来过滤掉继承的属性。

代码示例 3:使用 hasOwnProperty() 过滤继承属性

for (let key in alice) {
  if (alice.hasOwnProperty(key)) {
    console.log(`${key}: ${alice[key]}`);
  }
}

输出:

name: Alice
age: 25

现在,city 被成功过滤掉了,只保留了对象自身的属性。

3. Object.keys()Object.values()Object.entries():现代且优雅

随着 ES6 的引入,JavaScript 提供了更现代化的对象枚举方法:Object.keys()Object.values()Object.entries()。这些方法更加简洁、直观,并且不会遍历继承的属性,避免了 for...in 的一些问题。

3.1 Object.keys()

Object.keys() 返回一个包含对象自身所有可枚举属性名的数组。你可以把它想象成一张列出所有宝贝名字的清单。

代码示例 4:Object.keys()

const person = {
  name: 'Alice',
  age: 25,
  city: 'New York'
};

const keys = Object.keys(person);
console.log(keys); // ['name', 'age', 'city']

你可以结合 forEachfor...of 来遍历这些键:

代码示例 5:结合 forEach 遍历键

Object.keys(person).forEach(key => {
  console.log(`${key}: ${person[key]}`);
});

输出:

name: Alice
age: 25
city: New York

3.2 Object.values()

Object.values() 返回一个包含对象自身所有可枚举属性值的数组。这就像直接拿到了所有的宝贝,而不需要知道它们的名字。

代码示例 6:Object.values()

const values = Object.values(person);
console.log(values); // ['Alice', 25, 'New York']

3.3 Object.entries()

Object.entries() 返回一个包含对象自身所有可枚举属性的键值对数组。每个元素都是一个 [key, value] 的数组。这就像把宝贝的名字和宝贝本身一起列出来。

代码示例 7:Object.entries()

const entries = Object.entries(person);
console.log(entries); 
// [['name', 'Alice'], ['age', 25], ['city', 'New York']]

你可以使用 for...of 来遍历这些键值对:

代码示例 8:结合 for...of 遍历键值对

for (let [key, value] of Object.entries(person)) {
  console.log(`${key}: ${value}`);
}

输出:

name: Alice
age: 25
city: New York

4. 性能对比:for...in vs Object.keys/values/entries

那么,这两种方式在性能上有什么区别呢?其实,大多数情况下,性能差异并不明显。但在某些特定场景下,Object.keys/values/entries 可能会更高效,尤其是在处理大量数据时。

方法 特点 优点 缺点
for...in 遍历所有可枚举属性,包括继承的属性 语法简单,兼容性好 会遍历继承属性,可能导致意外行为
Object.keys() 返回对象自身的键数组 不会遍历继承属性,代码更清晰 需要额外的数组操作
Object.values() 返回对象自身的值数组 不会遍历继承属性,代码更简洁 需要额外的数组操作
Object.entries() 返回对象自身的键值对数组 不会遍历继承属性,适合同时获取键和值 需要额外的数组操作

5. 什么时候该用哪种方法?

  • for...in:如果你确实需要遍历所有可枚举属性,包括继承的属性,或者你需要向后兼容旧版本的 JavaScript,那么 for...in 是一个不错的选择。不过,记得使用 hasOwnProperty() 来过滤掉继承属性。

  • Object.keys/values/entries:如果你只需要遍历对象自身的属性,并且希望代码更简洁、直观,那么推荐使用这些方法。它们不仅能避免继承属性的问题,还能让你的代码更具可读性。

6. 结语

好了,今天的讲座就到这里啦!希望你现在对 JavaScript 中的对象枚举有了更清晰的理解。for...in 是一个经典的选择,但有时它可能会带来一些意想不到的麻烦。而 Object.keys/values/entries 则是更现代、更安全的选择,尤其适合处理复杂的对象结构。

如果你有任何问题,欢迎随时提问!下次见! 😊


引用:

  • MDN Web Docs: "The for...in statement iterates over all enumerable properties of an object that are keyed by strings."
  • ECMAScript Specification: "The Object.keys() method returns an array of a given object’s own enumerable property names, iterated in the same order that a normal loop would."
  • JavaScript.info: "The Object.entries() method returns an array of a given object’s own enumerable string-keyed property [key, value] pairs."

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注