|
总结下在JavaScript中遍历对象的几种方法。
for in
for in循环是最基础的遍历对象的方式,除了能拿到到对象自身的属性之外,它还能拿到对象原型链上的属性。
// 创建一个对象并指定其原型,yanggb为原型上的属性
const obj = Object.create({
yanggb: 'yanggb'
})
// yanggb1为对象自身的属性
obj.yanggb1 = 'yanggb1'
for (let key in obj) {
console.log(obj[key]) // yanggb1, yanggb
}
可以看到对象原型上的属性也被循环出来了,首先是遍历了自身的属性,然后逐层往上遍历原型链上原型的属性。
如果想要过滤掉原型链上的属性,也可以使用对象的hasOwnProperty()方法判断其是否是自身属性,以此来达到只针对自身的属性做相应操作的目的。
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(obj[key]) // yanggb1
}
}
这时候原型上的yanggb属性就被过滤掉了。
Object.keys
Object.keys()是ES5新增的一个对象方法,该方法返回对象自身属性名组成的数组,它会自动过滤掉原型链上的属性,然后可以通过数组的forEach()方法来遍历。
Object.keys(obj).forEach((key) => {
console.log(obj[key]) // yanggb1
})
此外还有Object.values()方法和Object.entries()方法,这两方法的作用范围和Object.keys()方法类似,分别是取得对象的属性值数组和属性键值数组数组。
for in循环和Object.keys()方法一样,都不会返回对象的不可枚举属性,如果需要遍历不可枚举的属性,就要使用Object.getOwnPropertyNames()方法了。
Object.getOwnPropertyNames
Object.getOwnPropertyNames()同样也是ES5新增的一个对象方法,该方法会返回对象自身属性名组成的数组,包括不可枚举的属性,因此也可以通过数组的forEach()方法来遍历。
// 创建一个对象并指定其原型,yanggb为原型上的属性
// yanggb1为对象自身的属性并且不可枚举
const obj = Object.create({
yanggb: 'yanggb'
}, {
yanggb1: {
value: 'yanggb1',
enumerable: false
}
})
obj.yanggb2 = 'yanggb2'
// 不包括不可枚举的yanggb1属性
Object.keys(obj).forEach((key) => {
console.log(obj[key]) // yanggb1
})
// 包括不可枚举的yanggb1属性
Object.getOwnPropertyNames(obj).forEach((key) => {
console.log(obj[key]) // yanggb1,yanggb2
})
而在ES2015新增了Symbol数据类型,该类型可以作为对象的键。针对该类型,ES2015同样新增了一个Object.getOwnPropertySymbols()方法。
Object.getOwnPropertySymbols
Object.getOwnPropertySymbols()方法返回对象自身的Symbol属性组成的数组,不包括字符串属性等其他属性。
Object.getOwnPropertySymbols(obj).forEach((key) => {
console.log(obj[key])
})
此时什么都没有输出,因为该对象还没有Symbol属性。
// 给对象添加一个不可枚举的Symbol属性
Object.defineProperties(obj, {
[Symbol('yanggb')]: {
value: 'Symbol yanggb',
enumerable: false
}
})
// 给对象添加一个可枚举的Symbol属性
obj[Symbol('yanggb1')] = 'Symbol yanggb1'
Object.getOwnPropertySymbols(obj).forEach((key) => {
console.log(obj[key]) // Symbol yanggb, Symbol yanggb1
})
这时候就会输出所有的Symbol属性,包括可枚举不可枚举Symbol属性。
Reflect.ownKeys
Reflect.ownKeys()方法是ES2015新增的一个静态方法,该方法返回对象自身所有属性名组成的数组,包括不可枚举的属性和Symbol属性。
Reflect.ownKeys(obj).forEach((key) => {
console.log(obj[key]) // yanggb, yanggb1, Symbol yanggb, Symbol yanggb1
})
既然方法有那么多,自然需要对比一下才能知道不同的场景该怎么选用。
几种方法的对比
通过一个表格直观得对比:
| 方式 |
基本属性 |
原型链 |
不可枚举 |
Symbol |
| for in |
是 |
是 |
否 |
否 |
| Object.keys() |
是 |
否 |
否 |
否 |
| Object.getOwnPropertyNames() |
是 |
否 |
是 |
否 |
| Object.getOwnPropertySymbols() |
否 |
否 |
是 |
是 |
| Reflect.ownKeys() |
是 |
否 |
是 |
是 |
这其中只有for in循环会得到对象原型链上的属性,其它方法都只适用于对象自身的属性。
ES语言后续添加的新特性不会对以前的代码产生副作用,比如在ES2015之前就存在的for in循环,Object.keys()和Object.getOwnPropertyNames()是肯定不会返回Symbol属性的。
"成长的经历,大概能让人变得越来越安静。"
你要去做一个大人,不要回头,不要难过。
来源:https://www.cnblogs.com/yanggb/p/13568354.html |