JS 5种遍历对象的方式

From: https://blog.csdn.net/qq_53225741/article/details/127073295

我根据阮老师的《ES6标准入门》学习并总结了七种遍历对象的方法,我会将分别介绍这七种方法并进行详细的区分,并将从属性可枚举性问题与遍历方法两个大方面讲述全文,其中可枚举性是掌握遍历对象之前的的铺垫,请读者耐心学习,掌握遍历对象的七种方法!

属性的可枚举性

为什么要先说属性的可枚举性问题,因为一些方法会根据属性的可枚举型进行操作,其中遍历就是一种,遍历的一些方法会忽略掉可枚举属性值为false的属性,我知道到这里读者可能会有一些绕圈子:什么叫可枚举属性值为false的属性?下面我带大家来一探究竟

对象中的所有属性都具有一个描述对象,对你没有看错,其实在我们看到的一个普通对象中的每一个属性值都包含一对象,即描述对象,它是用来控制属性的行为

let obj = {

name:"猪痞恶霸",

age:20

}

1

2

3

4

比如上面声明了一个普通的对象,含有name与age属性,这两个属性都具有一个描述对象,那我们怎么能拿到这个描述对象呢?

来看看这个方法:Object.getOwnPropertyDescriptor(),它可以拿到指定对象的某属性的描述对象,所以参数有两个,一个是指定对象,一共是指定对象的某属性

Object.getOwnPropertyDescriptor(obj,"name")

1

如上图,我们拿到了obj对象name属性的描述对象,描述对象内就包含了我们想知道的东西,enumerable就是描述对象可枚举属性,那么在这个例子中值为true,所以就能解释上面那句看不懂的话:可枚举属性值为false的属性,在这里的解释就为:obj对象内的name属性的描述对象内的可枚举属性值为true。

遍历对象

for…in

for...in可以遍历对象的所有可枚举属性,包括对象本身的和对象继承来的属性

let obj = {

name:"ned",

like:"man"

}

Object.defineProperty(obj, 'age', {

value: "18",

enumerable: false

});

for(item in obj) {

console.log(item)

}

1

2

3

4

5

6

7

8

9

10

11

看一看上面的例子,我们使用Object.defineProperty的形式来设置对象的描述对象,将其可枚举属性值设为false,使用for...in遍历,其没有被打印出来

其实for...in的特性会导致一个问题,其继承的属性会被遍历到,所以当我们不想要遍历被继承的属性,那么我们就可以使用Object.keys()

Object.keys()

Object.keys()方法可以遍历到所有对象本身的可枚举属性,但是其返回值为数组

let obj = {

name:"ned",

like:"man"

}

Object.keys(obj) // ['name', 'like']

1

2

3

4

5

到这里我们一般是使用Object.keys()来代替for...in遍历操作,除此之外,为了代替for...in,又新增了与Object.keys()配套的遍历方法,下面我们来看看

Object.values()

Object.values()与Object.keys()遍历对象的特性是相同的,但是其返回的结构是以遍历的属性值构成的数组

let obj = {

name:"cornd",

age:10

}

Object.values(obj) // ['cornd', 10]

Object.defineProperty(obj, 'like', {

value: "coding",

enumerable: false

});

Object.values(obj) // ['cornd', 10]

1

2

3

4

5

6

7

8

9

10

声明了一个对象,使用Object.values()返回对象的所有自身可枚举属性的属性值,通过设置新的属性值并将其描述对象内的enumerable设置为false,就可以看到Object.values()的特性

Object.entries()

Object.entries()的返回值为Object.values()与Object.keys()的结合,也就是说它会返回一个嵌套数组,数组内包括了属性名与属性值

let obj = {

name:"cornd",

age:10

}

Object.entries(obj) // [['name', 'cornd'],['age', 10]]

1

2

3

4

5

其遍历特性与Object.values()和Object.keys()相同,不再赘述。

Object.getOwnPropertyNames()

其返回结果与Object.keys()对应,但是他得特性与其相反,会返回对象得所有属性,包括了不可枚举属性

var arr = [];

console.log(Object.getOwnPropertyNames(arr)); // ['length']

Object.getOwnPropertyDescriptor(arr,"length").enumerable // false

1

2

3

上面我声明了一个空数组,而使用Object.getOwnPropertyNames()方法,返回了length,而length属性的enumerable正是false

Object.getOwnPropertySymbols()

Object.getOwnPropertySymbols()会返回对象内的所有Symbol属性,返回形式依旧是数组,值得注意的是,在对象初始化的时候,内部是不会包含任何Symbol属性

let obj = {

name:"obj"

}

Object.getOwnPropertySymbols(obj) // []

1

2

3

4

所以我初始化一个对象,通过这个方法返回的是一个空数组

let sym = Symbol()

console.log(sym)

obj[sym] = "hogskin"

Object.getOwnPropertySymbols(obj) // Symbol()

1

2

3

4

我在后面新建symbol,再为上面声明好的对象添加进去,通过遍历得到Symbol()

Reflect.ownKeys()

Reflect.ownKeys()返回的是一个大杂烩数组,即包含了对象的所有属性,无论是否可枚举还是属性是symbol,还是继承,将所有的属性返回

let arr = [0,31,2]

Reflect.ownKeys(arr) // ['0', '1', '2', 'length']

1

2

上面的例子声明了一个数组,返回的是数组下标和length属性。

区分

为了跟好的记忆理解并掌握这七种方法,我根据遍历目标,返回形式,遍历值三个维度将七种方法区分起来。

根据遍历目标区分

遍历目标方法

遍历对象本身的可枚举属性不包含继承来的属性(不包括Symbol())Object.keys(),Object.values(),Object.entries()

遍历对象本身的可枚举属性包括继承来的属性(不包括Symbol())for...in

遍历对象本身的所有属性(不包括Symbol())Object.getOwnPropertyNames()

遍历对象的Symbol()属性Object.getOwnPropertySymbols()

遍历对象的所有属性Reflect.ownKeys()

根据返回值区分

返回值方法

返回数组`Object.keys(),Object.values(),Object.entries(),Object.getOwnPropertyNames(),Object.getOwnPropertySymbols(),Reflect.ownKeys()

不返回值for...in

根据遍历值区分

遍历值方法

遍历属性Reflect.ownKeys(),Object.getOwnPropertyNames(),Object.keys()

遍历属性值Object.getOwnPropertySymbols(),Object.values()

遍历全部for...in,Object.entries()

最后

为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值