JS中如何轻松遍历对象属性的方式总结
自身可枚举属性
Object.keys()方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用for...in循环遍历该对象时返回的顺序一致。如果对象的键-值都不可枚举,那么将返回由键组成的数组。
这是合理的,因为大多数时候只需要关注对象自身的属性。
来看看一个对象拥有自身和继承属性的例子,Object.keys()只返回自己的属性键:
letsimpleColors={ colorA:'white', colorB:'black' }; letnatureColors={ colorC:'green', colorD:'yellow' }; Object.setPrototypeOf(natureColors,simpleColors); Object.keys(natureColors);//=>['colorC','colorD'] natureColors['colorA'];//=>'white' natureColors['colorB'];//=>'black'
Object.setPrototypeOf()方法设置一个指定的对象的原型(即,内部[[Prototype]]属性)到另一个对象或null。
Object.keys(natureColors)返回natureColors对象的自身可枚举属性键:['colorC','colorD']。
natureColors包含从simpleColors原型对象继承的属性,但是Object.keys()函数会跳过它们。
Object.values()和Object.entries()也都是返回一个给定对象自身可枚举属性的键值对数组
//... Object.values(natureColors); //=>['green','yellow'] Object.entries(natureColors); //=>[['colorC','green'],['colorD','yellow']]
现在注意与for..in语句的区别,for..in不仅可以循环枚举自身属性还可以枚举原型链中的属性
//... letenumerableKeys=[]; for(letkeyinnatureColors){ enumerableKeys.push(key); } enumerableKeys;//=>['colorC','colorD','colorA','colorB']
enumerableKeys数组包含natureColors自身属性键:'colorC'和'colorD'。
另外for..in也遍历了从simpleColors原型对象继承的属性
2.Object.values()返回属性值
Object.values()方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同(区别在于for-in循环枚举原型链中的属性)。
来个例子,使用Object.keys()收集keys,然后通过key去对象取对应的值:
letmeals={ mealA:'Breakfast', mealB:'Lunch', mealC:'Dinner' }; for(letkeyofObject.keys(meals)){ letmealName=meals[key]; //...dosomethingwithmealName console.log(mealName); } //'Breakfast''Lunch''Dinner'
meal是一个普通对象。使用Object.keys(meals)和枚举的for..of循环获取对象键值。
代码看起来很简单,但是,letmealName=meals[key]没有多大的必要,可以进一步优化,如下:
letmeals={ mealA:'Breakfast', mealB:'Lunch', mealC:'Dinner' }; for(letmealNameofObject.values(meals)){ console.log(mealName); } //'Breakfast''Lunch''Dinner'
因为Object.values(meals)返回数组中的对象属性值,所以可以直接在for..of中简化。mealName直接在循环中赋值。
Object.entries()
Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用for...in循环遍历该对象时返回的顺序一致(区别在于for-in循环也枚举原型链中的属性)。
Object.entries()返回键值对数组,如[[key1,value1],[key2,value2],...,[keyN,valueN]]。
可能直接使用这些键值对不怎么方便,但可以通过数组解构赋值方式访问键和值就变得非常容易,如下所示:
letmeals={ mealA:'Breakfast', mealB:'Lunch', mealC:'Dinner' }; for(let[key,value]ofObject.entries(meals)){ console.log(key+':'+value); } //'mealA:Breakfast''mealB:Lunch''mealC:Dinner'
如上所示,因为Object.entries()返回一个与数组解构赋值兼容的集合,因此不需要为赋值或声明添加额外的行。
当普通对象要转换成Map时Object.entries()就很有用,因为Object.entries()返回的格式与Map构造函数接受的格式完全相同:(key,value)。
使用常规的Map构造函数可以将一个二维键值对数组转换成一个Map对象。
来个例子,让人缓缓:
letgreetings={ morning:'Goodmorning', midday:'Goodday', evening:'Goodevening' }; letgreetingsMap=newMap(Object.entries(greetings)); greetingsMap.get('morning');//=>'Goodmorning' greetingsMap.get('midday');//=>'Goodday' greetingsMap.get('evening');//=>'Goodevening'
Map对象保存键值对。任何值(对象或者原始值)都可以作为一个键或一个值。
有趣的是,Map提供了与Object.values()和Object.entries()等效的方法(只是它们返回Iterators),以便为Map实例提取属性值或键值对:
- Map.prototype.values()等价于Object.values()
- Map.prototype.entries()等价于Object.entries()
map是普通对象的改进版本,可以获取map的大小(对于普通对象,必须手动获取),并使用任意对象类型作为键(普通对象使用字符串基元类型作为键)。
让我们看看返回.values()和.entries()的map的方法:
//... [...greetingsMap.values()]; //=>['Goodmorning','Goodday','Goodevening'] [...greetingsMap.entries()]; //=>[['morning','Goodmorning'],['midday','Goodday'], //['evening','Goodevening']]
注意,greetingsMap.values()和greetingsMap.entries()返回迭代器对象。若要将结果放入数组,扩展运算符…是必要的。
对象属性的顺序
JS对象是简单的键值映射,因此,对象中属性的顺序是微不足道的,在大多数情况下,不应该依赖它。
在ES5和早期标准中,根本没有指定属性的顺序。
然而,从ES6开始,属性的顺序是基于一个特殊的规则的,除非特指按照时间排序。通过两个新方法Object.getOwnPropertyNames和Reflect.ownKeys来编写示例讲解这一属性排序规则。
- 数字:当属性的类型时数字类型时,会按照数字的从大到小的顺序进行排序;
- 字符串:当属性的类型是字符串时,会按照时间的先后顺序进行排序;
- Symbol:当属性的类型是Symbol时,会按照时间的先后顺序进行排序。
如果需要有序集合,建议将数据存储到数组或Set中。
总结
Object.values()和Object.entries()是为JS开发人员提供新的标准化辅助函数的另一个改进步骤。
Object.entries()最适用于数组解构赋值,其方式是将键和值轻松分配给不同的变量。此函数还可以轻松地将纯JS对象属性映射到Map对象中。、
注意,Object.values()和Object.entries()返回数据的顺序是不确定的,所以不要依赖该方式。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对毛票票的支持。