Javascript - 对象也可以循环吗?

2025-05-25

Javascript - 对象也可以循环吗?

好吧,再见!

之前我讨论过数组循环,从循环的基础知识到数组循环方法的使用。如果你还没读过,那就直接去阅读原文吧!👇

这次我想讨论一下另一个和循环相关的东西,那就是对象。不过话说回来,对象也可以循环吗?


理解 JavaScript 中的对象

你有没有想过 JavaScript 中存在哪些类型?好吧,虽然 JavaScript 是弱类型语言(注意,你甚至不需要声明你的let“和”const是“string或”number还是其他什么),但我们仍然可以获取变量的类型。

要知道你的变量是什么类型,只需使用typeof

const name = "Naruto";
console.log(typeof name); // "string"

const team7 = ["Naruto", "Sasuke", "Sakura", "Kakashi", "Sai", "Yamato"];
console.log(typeof team7); // "object"
Enter fullscreen mode Exit fullscreen mode

JavaScript 有两种常见的变量类型:原始类型和对象。原始类型包括字符串、数字、符号和布尔值。此外,还有对象。

还记得我说过数组也是对象吗?嗯,就是这样的。数组是一个对象,附加了某些特性,从而支持多种方法,例如.map.forEach等等。虽然这使得数组可迭代,但原生对象却不具备这些特性。这意味着我们之前讨论过的所有数组循环方法都不能用于对象。

const character = {
  name: "Naruto",
  position: "Hokage",
  village: "Leaf Village",
  country: "Fire Country",
};

character.forEach(); // This will throw error for sure!
Enter fullscreen mode Exit fullscreen mode

那么,我们如何迭代对象呢?🤔


回到循环基础

我们已经讨论过 JavaScript 中循环的几种方式,主要是forwhiledo...while。之后,我告诉过你有两种可用的循环,一种用于数组,一种用于对象。你还记得它们分别是什么吗?

for...of用于数组。由于索引是按顺序排列的,因此无需获取索引,除非您需要索引。

const team7 = ["Naruto", "Sasuke", "Sakura", "Kakashi", "Sai", "Yamato"];

for (let member of team7) {
  console.log(member)
}

/*
The output should be

Naruto
Sasuke
Sakura
Kakashi
Sai
Yamato

*/
Enter fullscreen mode Exit fullscreen mode

另一方面,for...in是专门针对对象的。虽然循环只为你获取了键,但其余部分你都知道。

const character = {
  name: "Naruto",
  position: "Hokage",
  village: "Leaf Village",
  country: "Fire Country",
};

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

/*
The output should be

name: Naruto
position: Hokage
village: Leaf Village
country: Fire Country

*/
Enter fullscreen mode Exit fullscreen mode

好了,关于循环对象就这些了……等等!如果你想使用我们之前讨论过的数组循环方法,还有另一种方法。但这意味着,我们需要把对象转换成数组,对吗?


对象作为数组

在某些紧急情况下,你不得不用不同的方法执行任务。虽然我们已经有了for...infor 对象,但我们还有“其他方法”来循环对象。

当然,我们需要将对象转换为数组,这样对象才能访问数组循环方法提供的所有功能。虽然根据我的经验,这并没有那么麻烦,但当你遇到其他数据结构时,尤其是在 Python 中存在字典和元组时,它非常有用。

好吧,我们可以吗?


Object.keys

如果您只需要对象中的键,for...in那么这已经做得很好了。但是,有一种方法可以将其转换为仅包含键的数组。使用ObjectJavaScript 中的类,我们可以使用所有对象提供的方法。是的,我的意思是,所有对象!这意味着数组也可以使用这些方法,但是这是为了什么呢?对吧?

一种Object方法是.keys,它将转换为对象的键列表。

const character = {
  name: "Naruto",
  position: "Hokage",
  village: "Leaf Village",
  country: "Fire Country",
};

console.log(Object.keys(character));
// ["name", "position", "village", "country"]
Enter fullscreen mode Exit fullscreen mode

如你所见,结果将是一个数组。那么,你知道我们要做什么吗?没错!数组循环方法!你可以使用所有数组循环方法,也许只是为了防止你不需要某个属性,或者你需要统计所有字母的数量,又或者所有以“A”开头的字母?谁知道你的用例是什么呢?但这很简洁,对吧?


Object.values

当然,当我们谈论对象时,我们需要的是值。做这件事的方法是Object.values

const character = {
  name: "Naruto",
  position: "Hokage",
  village: "Leaf Village",
  country: "Fire Country",
};

console.log(Object.values(character));
// ["Naruto", "Hokage", "Leaf Village", "Fire Country"]
Enter fullscreen mode Exit fullscreen mode

除了获取键之外,我们可以直接获取对象中的所有值。然后,继续使用数组循环方法。但是如何同时获取键和值呢?


Object.entries

Object我最常使用的最后一个方法是Object.entries,因为我需要键和值来根据键执行我的功能。

const character = {
  name: "Naruto",
  position: "Hokage",
  village: "Leaf Village",
  country: "Fire Country",
};

console.log(Object.entries(character));
// [["name", "Naruto"], ["position", "Hokage"], ["village", "Leaf Village"], ["country", "Fire Country"]]
Enter fullscreen mode Exit fullscreen mode

那么,你注意到了什么?嗯,.keys生成.values一维数组,但.entries生成二维数组。这意味着,如果我使用方法,我仍然需要调用它对应的索引,对吗?就像 entry[0] 和 entry[1] 那样?


解构二维数组

好吧,我将来会写一篇关于解构的更具描述性的文章,但我会尽力解释它是如何工作的,特别是针对数组循环方法Object.entries

举个例子,我们将有一个对象,列出火影忍者时代忍者团队的所有成员(对于非动漫迷,请稍等片刻😖)。

const konohaNinja = {
  sandSibling: ["Gaara", "Kankuro", "Temari"],
  team7: ["Naruto", "Sasuke", "Sakura", "Kakashi"],
  team8: ["Shino", "Hinata", "Kiba", "Kurenai"],
  teamGuy: ["Rock Lee", "Neji", "Tenten", "Mighty Guy"],
  team10: ["Ino", "Shikamaru", "Choji", "Asuma"],
};
Enter fullscreen mode Exit fullscreen mode

看看这个对象的结构?键包含团队名称,值包含团队所有成员。这是一个复杂的数据结构🥶。那么,我应该如何处理这个解决方案呢?当然,我需要先拆分团队。

const konohaTeams = Object.entries(konohaNinja);
Enter fullscreen mode Exit fullscreen mode

现在,我可以用这个数组做各种各样的事情了。比如,创建一个字符串,内容是“{team} 的成员是 {team members}”怎么样?

const teams = konohaTeams.map(([teamName, teamMembers]) => {
  return `The members of ${teamName} are ${teamMembers.join(", ")}`;
});
Enter fullscreen mode Exit fullscreen mode

哎呀,这到底是怎么回事?好吧,我得承认,这里面确实发生了很多事。那就让我一层一层地讲吧。

还记得我使用 时.map传递了每个索引的值吗?是的,我就是这么做的。所以,我应该这样写。

const teams = konohaTeams.map((team) => {
  /**
  * since konohaTeams is a 2-dimensional array,
  * (in this case, 3-dimensional array in fact),
  * when you loop the object-turns-array, you will still get
  * the array, except now you know all subarray has 2 elements
  * only, which is key-value pair, given team[0] is a team name
  * and team[1] is the array of team members
  */

  return `The members of ${team[0]} are ${team[1].join(", ")}`;
});
Enter fullscreen mode Exit fullscreen mode

然而,它很难读懂。也许你已经知道 team[0] 是什么,team[1] 代表什么。但是,如果你能理解变量的含义,是不是会更好呢?当然,有更好的方法。

const teams = konohaTeams.map((team) => {
  const teamName = team[0];
  const teamMembers = team[1];

  return `The members of ${teamName} are ${teamMembers.join(", ")}`;
});
Enter fullscreen mode Exit fullscreen mode

这一步比上一个例子好多了。你重命名每个键和值,然后在返回结果中使用它。但是你知道吗,解构可以帮你做这么多,而且语法更简洁。

const teams = konohaTeams.map((team) => {
  const [teamName, teamMembers] = team;

  return `The members of ${teamName} are ${teamMembers.join(", ")}`;
});
Enter fullscreen mode Exit fullscreen mode

这里发生了什么?我们都已经知道索引 0 等于 teamName,索引 1 等于 teamMembers。使用声明式提取数组的方法,我们可以重命名每个索引,这样稍后在函数中就可以使用它们了。更简洁明了,对吧?好吧,我们可以更简洁一些吗?当然,与其在函数内部解构,不如在参数传递过程中解构呢?这就是为什么我们现在将 from 替换(team) =>([teamName, teamMembers]) =>

const teams = konohaTeams.map(([teamName, teamMembers]) => {
  return `The members of ${teamName} are ${teamMembers.join(", ")}`;
});

console.log(teams);
/*
The output should be
[
  "The members of sandSibling are Gaara, Kankuro, Temari,",
  "The members of team7 are Naruto, Sasuke, Sakura, Kakashi,",
  "The members of team8 are Shino, Hinata, Kina, Kurenai,",
  "The members of teamGuy are Rock Lee, Neji, Tenten, Mighty Guy,",
  "The members of team10 are Ino, Shikamaru, Choji, Asuma,"
]
Enter fullscreen mode Exit fullscreen mode

我知道,对于一些初学者来说,这个概念很难掌握,但请尝试一步一步地理解这里发生的事情。


结论

这里的重点是,对象也可以循环,就像循环数组一样。在将对象转换为数组时,我们已经提供了赋予数组的功能,并将其用于对象。

当然,还有很多事情要做,但是如果你掌握了如何循环数组和对象,以及如何修改它们,无论是通过更改原始对象还是使用数组循环方法从中创建一个新实体,我相信你现在可以成为一名非常优秀的 Javascript 程序员。

好吧,下周见,愿你平安!

文章来源:https://dev.to/alserembani/javascript-object-is-loopable-too-7fo
PREV
100天CSS插图
NEXT
🗿 人类为何发明 HTML - 深入学习前端 - 第一部分