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

作者:Dmitri paylutin    译者:前端小智   来源:dmitripavlutin

阿里云最近在做活动,低至2折,有兴趣可以看看:

https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=pxuujn3r

 

为了保证的可读性,本文采用意译而非直译。

自身可枚举属性

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循环获取对象键值。

代码看起来很简单,但是, letmealName=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'

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()];	
// => ['Good morning', 'Good day', 'Good evening']	
[...greetingsMap.entries()];	
// => [ ['morning', 'Good morning'], ['midday', 'Good day'],	
//      ['evening', 'Good evening'] ]

注意, greetingsMap.values()和 greetingsMap.entries()返回迭代器对象。若要将结果放入数组,扩展运算符 是必要的。

对象属性的顺序

JS 对象是简单的键值映射,因此,对象中属性的顺序是微不足道的, 在大多数情况下,不应该依赖它。

在ES5和早期标准中,根本没有指定属性的顺序。

然而,从ES 6开始,属性的顺序是基于一个特殊的规则的,除非特指按照时间排序。通过两个新方法 Object.getOwnPropertyNames和 Reflect.ownKeys来编写示例讲解这一属性排序规则。

  • 数字:当属性的类型时数字类型时,会按照数字的从大到小的顺序进行排序;

  • 字符串:当属性的类型是字符串时,会按照时间的先后顺序进行排序;

  • Symbol:当属性的类型是Symbol时,会按照时间的先后顺序进行排序。

如果需要有序集合,建议将数据存储到数组或 Set中。

原文:https://dmitripavlutin.com/how-to-iterate-easily-over-object-properties-in-javascript/

总结

Object.values() 和 Object.entries() 是为JS开发人员提供新的标准化辅助函数的另一个改进步骤。

Object.entries()最适用于数组解构赋值,其方式是将键和值轻松分配给不同的变量。此函数还可以轻松地将纯JS对象属性映射到 Map对象中。、

注意, Object.values()和 Object.entries()返回数据的顺序是不确定的,所以不要依赖该方式。

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。

 

交流

极客学院给我两个年卡的优惠,原价260,现在一张只要100,需要的后台进群交流,二维码加我微信,只有两张。

我是小智,公众号「大迁世界」作者,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!

关注公众号,后台回复福利,即可看到福利,你懂的。

JS中轻松遍历对象属性的几种方式_第1张图片

每次整理文章,一般都到2点才睡觉,一周4次左右,挺苦的,还望支持,给点鼓励

JS中轻松遍历对象属性的几种方式_第2张图片

你可能感兴趣的:(前端,javascript,java)