用法
我们先看下用法:
js
代码解读
复制代码
const person = { name: '张三', age: 30, job: '工程师' }; for (const key in person) { console.log(key + ': ' + person[key]); } // 输出: // name: 张三 // age: 30 // job: 工程师
概念
for...in 语句迭代一个对象的除了Symbol以外的所有 可枚举 字符串属性,包含从原型链上 继承 的可枚举属性。
新词汇:可枚举 ,看看这个什么意思
可枚举
可枚举属性是指那些内部的 可枚举属性 设置为true的属性。 可能第一次接触有点抽象,我们逐步展开。
JS可以使用 Object.defineProperty() 方法直接在对象上定义一个新属性,或者修改对象上的现有属性,并返回该对象。
js
代码解读
复制代码
const obj = {}; Object.defineProperty(obj, 'name', { value: '张三', // 属性的值 writable: true, // 是否可写 enumerable: true, // 是否可枚举 configurable: true // 是否可配置 }); console.log(obj.name); // "张三"
聪明的你这时候肯定就明白了对象中的属性可以被枚举就是因为 enumerable 描述符为 true的情况下。
需要注意的是:
- 如果直接使用 Object.defineProperty() 去定义一个属性值,但是其他的描述都不配置,默认都是false。
- 如果我们直接通过赋值的属性或者直接初始化一个对象创建的属性,则他们的属性的标识符默认是true。
for...in 返回的顺序
for...in 遍历对象时,虽然顺序不是按照声明顺序返回的,但是遍历的顺序也是可以预测的(ES6之后):
- 首先是所有非负整数键按值的升序遍历
- 其他字符串按属性创建的先后顺序升序遍历
js
代码解读
复制代码
const obj = { 2: 'two', 1: 'one', b: 'b', abc: 'ABC', a: 'a' }; for (const key in obj) { console.log(key); // 输出顺序: "1", "2", "b", "abc", "a" }
至此,我们已经了解完for...in了。
for...in 的数组迭代
我们知道 JS中万物皆对象,数组也是一样。数组只不过是将他的索引作为了属性,除此之外与一般对象属性完全相同。
js
代码解读
复制代码
const colors = ['red', 'green', 'blue']; for (const index in colors) { console.log(index + ': ' + colors[index]); } // 输出: // 0: red // 1: green // 2: blue
需要注意的是for...in使用的是数组的属性枚举,而for...of是使用的数组的迭代器。
这个差别就体现在了遍历稀疏数组上,for...of会访问空槽,for...in会跳过空槽,只遍历有值得属性。
js
代码解读
复制代码
// 创建一个稀疏数组 const sparseArray = [1, , 3]; // 注意中间的逗号表示空槽 sparseArray[4] = 5; // 索引2和3是空槽 console.log(sparseArray); // [1, empty, 3, empty, 5] // 使用 for...of 遍历 console.log('for...of 遍历:'); for (const value of sparseArray) { console.log(value); } // 输出: // 1 // undefined (空槽) // 3 // undefined (空槽) // 5 // 使用 for...in 遍历 console.log('for...in 遍历:'); for (const index in sparseArray) { console.log(`索引 ${index}: ${sparseArray[index]}`); } // 输出: // 索引 0: 1 // 索引 2: 3 (跳过了空槽1) // 索引 4: 5 (跳过了空槽3)
仅遍历自身属性
因为for...in 是可以迭代原型链上的属性:
js
代码解读
复制代码
function Person() { this.name = 'Alice'; } Person.prototype.age = 30; const p = new Person(); for (const key in p) { console.log(key); // 'name', 'age' }
但是我们一般平时的开发中,需求大多数都是遍历自身的属性,并且也是希望遍历的顺序是我们期望的,可以看看一下方法
1. 使用 Object.keys()
+ forEach()
/ for...of
js
代码解读
复制代码
const obj = { a: 1, b: 2 }; // 方案1: forEach Object.keys(obj).forEach(key => { console.log(key, obj[key]); }); // 方案2: for...of for (const key of Object.keys(obj)) { console.log(key, obj[key]); }
2. Object.entries()
(ES2017+)
js
代码解读
复制代码
const obj = { a: 1, b: 2 }; // 方案1: forEach Object.entries(obj).forEach(([key, value]) => { console.log(key, value); }); // 方案2: for...of for (const [key, value] of Object.entries(obj)) { console.log(key, value); }
新手前端,不正确的地方,期望指正!
原文:https://juejin.cn/post/7491892638870798375