JS中轻松遍历对象属性的几种方式

原文:dmitripavlutin.com/how-to-iter…
译者:前端小智
为了保证的可读性,本文采用意译而非直译 。
想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!
自身可枚举属性
Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致。如果对象的键-值都不可枚举,那么将返回由键组成的数组 。
这是合理的,因为大多数时候只需要关注对象自身的属性 。
来看看一个对象拥有自身和继承属性的例子,Object.keys()只返回自己的属性键:
let simpleColors = { colorA: 'white', colorB: 'black'};let natureColors = { 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不仅可以循环枚举自身属性还可以枚举原型链中的属性
// ...let enumerableKeys = [];for (let key in natureColors) { 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 去对象取对应的值:
let meals = { mealA: 'Breakfast', mealB: 'Lunch', mealC: 'Dinner'};for (let key of Object.keys(meals)) { let mealName = meals[key]; // ... do something with mealName console.log(mealName);}// 'Breakfast' 'Lunch' 'Dinner'复制代码meal是一个普通对象 。使用Object.keys(meals)和枚举的for..of循环获取对象键值 。
代码看起来很简单,但是,let mealName = meals[key] 没有多大的必要,可以进一步优化,如下:
let meals = { mealA: 'Breakfast', mealB: 'Lunch', mealC: 'Dinner'};for (let mealName of Object.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] ] 。
可能直接使用这些键值对不怎么方便,但可以通过数组解构赋值方式访问键和值就变得非常容易,如下所示:
let meals = { mealA: 'Breakfast', mealB: 'Lunch', mealC: 'Dinner'};for (let [key, value] of Object.entries(meals)) { console.log(key + ':' + value);}// 'mealA:Breakfast' 'mealB:Lunch' 'mealC:Dinner'复制代码如上所示,因为 Object.entries()返回一个与数组解构赋值兼容的集合,因此不需要为赋值或声明添加额外的行 。
当普通对象要转换成 Map 时Object.entries() 就很有用,因为Object.entries() 返回的格式与Map构造函数接受的格式完全相同:(key,value) 。
使用常规的Map构造函数可以将一个二维键值对数组转换成一个Map对象 。
来个例子,让人缓缓:
let greetings = { morning: 'Good morning', midday: 'Good day', evening: 'Good evening'};let greetingsMap = new Map(Object.entries(greetings));greetingsMap.get('morning'); // => 'Good morning'greetingsMap.get('midday'); // => 'Good day'greetingsMap.get('evening'); // => 'Good evening'复制代码


推荐阅读