for...of
和 for...in
是两种 JavaScript 中不同的循环结构,它们有一些区别:
-
适用范围:
for...of
用于迭代可迭代对象(例如数组、字符串、Map、Set等),可以遍历值。for...in
用于遍历对象的可枚举属性,包括对象的原型链上的属性。
-
迭代的内容:
for...of
遍历的是对象的值,不包括对象的键或索引。for...in
遍历的是对象的键,包括可枚举的自有属性以及继承的属性。
-
顺序:
for...of
保证按照对象的迭代顺序进行迭代,例如数组的元素按照它们在数组中的顺序被访问。for...in
并不保证属性的顺序,因为对象属性的顺序在 JavaScript 中并不是固定的。
-
支持的对象类型:
for...of
适用于迭代器对象(具有Symbol.iterator
方法的对象)。for...in
适用于所有对象。
下面是它们的简单示例:
// 使用 for...of 迭代数组
const arr = [1, 2, 3];
for (const value of arr) {
console.log(value);
}
// 使用 for...in 迭代对象的键
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
console.log(key, obj[key]);
}
总体而言,如果你需要遍历数组或其他可迭代对象的值,使用 for...of
更直观和方便;如果需要遍历对象的键,使用 for...in
较为合适。
在 JavaScript 中,对象的属性分为可枚举属性和不可枚举属性。这两者的主要区别在于它们是否会出现在对象的属性枚举中。
-
可枚举属性(Enumerable): 可以通过
for...in
循环遍历到的属性称为可枚举属性。大多数通过字面量方式创建的属性都是可枚举的。 -
不可枚举属性(Non-enumerable): 不会出现在
for...in
循环中的属性称为不可枚举属性。
JavaScript 中的内置对象通常包含一些不可枚举属性,这些属性通常用于存储对象的内部状态或实现某些特殊功能。例如,Object.prototype
中的一些方法(例如 toString
、hasOwnProperty
)是不可枚举的。
通过以下示例可以说明可枚举和不可枚举属性的区别:
const obj = { a: 1, b: 2 }; // 添加一个可枚举属性
obj.c = 3;
// 使用 defineProperty 添加一个不可枚举属性
Object.defineProperty(obj, 'd', { value: 4, enumerable: false });
// 遍历可枚举属性
for (let key in obj) {
console.log(key); // 输出 'a', 'b', 'c'
} // 获取所有属性,包括不可枚举属性
const allProperties = Object.getOwnPropertyNames(obj);
console.log(allProperties); // 输出 ['a', 'b', 'c', 'd']
在上面的例子中,属性 a
、b
、c
都是可枚举的,而属性 d
是不可枚举的。for...in
循环只会遍历可枚举属性,而 Object.