JavaScript 中使用什么语言结构来迭代对象属性和数组项?
TL;DR
在 JavaScript 中,有多种方法可以迭代对象属性和数组:
for...in
循环
for...in
循环遍历对象的所有可枚举属性,包括继承的可枚举属性。因此,如果您只想遍历对象的自有属性,进行检查非常重要
const obj = {a: 1,b: 2,c: 3,};for (const key in obj) {// To avoid iterating over inherited propertiesif (Object.hasOwn(obj, key)) {console.log(`${key}: ${obj[key]}`);}}
Object.keys()
Object.keys()
返回一个由对象自身的可枚举属性名称组成的数组。然后,您可以使用 for...of 循环或 forEach 遍历此数组。
const obj = {a: 1,b: 2,c: 3,};Object.keys(obj).forEach((key) => {console.log(`${key}: ${obj[key]}`);});
迭代数组最常见的方法是使用 for
循环和 Array.prototype.forEach
方法。
使用 for
循环
let array = [1, 2, 3, 4, 5, 6];for (let index = 0; index < array.length; index++) {console.log(array[index]);}
使用 Array.prototype.forEach
方法
let array = [1, 2, 3, 4, 5, 6];array.forEach((number, index) => {console.log(`${number} at index ${index}`);});
使用 for...of
此方法是迭代数组的最新和最方便的方法。它会自动迭代每个元素,而无需您管理索引。
const numbers = [1, 2, 3, 4, 5];for (const number of numbers) {console.log(number);}
还有其他可用的内置方法,适用于特定场景,例如:
Array.prototype.filter
:您可以使用filter
方法创建一个新数组,其中仅包含满足特定条件的元素。Array.prototype.map
:您可以使用map
方法基于现有数组创建一个新数组,并使用提供的函数转换每个元素。Array.prototype.reduce
:您可以使用reduce
方法通过重复调用一个接受两个参数的函数(累积值和当前元素)将所有元素组合成一个值。
遍历对象
在 JavaScript 中,遍历对象属性和数组非常常见,我们有多种方法可以实现这一点。以下是实现此目的的一些方法:
for...in
语句
此循环遍历对象的所有可枚举属性,包括从其原型链继承的属性。
const obj = {status: 'working',hoursWorked: 3,};for (const property in obj) {console.log(property);}
由于 for...in
语句遍历对象的所有可枚举属性(包括继承的可枚举属性)。因此,大多数情况下,在使用属性之前,您应该通过 Object.hasOwn(object, property)
检查该属性是否存在于对象上。
const obj = {status: 'working',hoursWorked: 3,};for (const property in obj) {if (Object.hasOwn(obj, property)) {console.log(property);}}
请注意,不推荐使用 obj.hasOwnProperty()
,因为它不适用于使用 Object.create(null)
创建的对象。建议在较新的浏览器中使用 Object.hasOwn()
,或者使用旧的 Object.prototype.hasOwnProperty.call(object, key)
。
Object.keys()
Object.keys()
是一种静态方法,它将返回您传递给它的对象的所有可枚举属性名称的数组。由于 Object.keys()
返回一个数组,您也可以使用下面列出的数组迭代方法来遍历它。
const obj = {status: 'working',hoursWorked: 3,};Object.keys(obj).forEach((property) => {console.log(property);});
Object.entries()
:
此方法返回一个对象的可枚举属性的数组,以 [key, value]
对的形式。
const obj = { a: 1, b: 2, c: 3 };Object.entries(obj).forEach(([key, value]) => {console.log(`${key}: ${value}`);});
Object.getOwnPropertyNames()
const obj = { a: 1, b: 2, c: 3 };Object.getOwnPropertyNames(obj).forEach((property) => {console.log(property);});
Object.getOwnPropertyNames()
是一种静态方法,它将列出您传递给它的对象的所有可枚举和不可枚举属性。由于 Object.getOwnPropertyNames()
返回一个数组,您也可以使用下面列出的数组迭代方法来遍历它。
数组
for
循环
const arr = [1, 2, 3, 4, 5];for (var i = 0; i < arr.length; i++) {console.log(arr[i]);}
这里一个常见的陷阱是 var
在函数作用域中,而不是块作用域中,并且大多数情况下您希望使用块作用域迭代器变量。 ES2015 引入了具有块作用域的 let
,建议使用 let
而不是 var
。
const arr = [1, 2, 3, 4, 5];for (let i = 0; i < arr.length; i++) {console.log(arr[i]);}
Array.prototype.forEach()
const arr = [1, 2, 3, 4, 5];arr.forEach((element, index) => {console.log(`${element} at index ${index}`);});
Array.prototype.forEach()
方法有时会更方便,如果您不需要使用 index
,而您只需要单个数组元素。 但是,缺点是您无法中途停止迭代,并且提供的函数将在元素上执行一次。 如果您需要更好地控制迭代,for
循环或 for...of
语句会更相关。
for...of
语句
const arr = [1, 2, 3, 4, 5];for (let element of arr) {console.log(element);}
ES2015 引入了一种新的迭代方式,即 for-of
循环,它允许您循环访问符合 iterable protocol 的对象,例如 String
、Array
、Map
、Set
等。 它结合了 for
循环和 forEach()
方法的优点。 for
循环的优点是您可以从中跳出,而 forEach()
的优点是它比 for
循环更简洁,因为您不需要计数器变量。 使用 for...of
语句,您可以同时获得跳出循环的能力和更简洁的语法。
大多数情况下,更喜欢 .forEach
方法,但这确实取决于您要执行的操作。 在 ES2015 之前,当我们需要使用 break
提前终止循环时,我们使用 for
循环。 但现在有了 ES2015,我们可以使用 for...of
语句来做到这一点。 当您需要更大的灵活性时,例如每次循环递增迭代器一次以上时,请使用 for
循环。
此外,在使用 for...of
语句时,如果您需要访问每个数组元素的索引和值,您可以使用 ES2015 Array.prototype.entries()
方法来实现:
const arr = ['a', 'b', 'c'];for (let [index, elem] of arr.entries()) {console.log(index, elem);}