这篇文章终于搞明白了 for...in 了

用法

我们先看下用法:

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值