总结下在JavaScript中遍历对象的几种方法。
for in
for in循环是最基础的遍历对象的方式,除了能拿到到对象自身的属性之外,它还能拿到对象原型链上的属性。
// 创建一个对象并指定其原型,yanggb为原型上的属性 const obj = Object.create({ yanggb: ‘yanggb‘ }) // foo为对象自身的属性 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