JS中轻松遍历对象属性的几种方式
原文:dmitripavlutin.com/how-to-iter…
译者:前端小智
为了保证的可读性,本文采用意译而非直译。
自身可枚举属性
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'
复制代码
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
中。
总结
Object.values()
和Object.entries()
是为JS开发人员提供新的标准化辅助函数的另一个改进步骤。
Object.entries()
最适用于数组解构赋值,其方式是将键和值轻松分配给不同的变量。 此函数还可以轻松地将纯JS对象属性映射到Map
对象中。、
注意,Object.values()
和Object.entries()
返回数据的顺序是不确定的,所以不要依赖该方式。
代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。
交流(欢迎加入群,群工作日都会发红包,互动讨论技术)
干货系列文章汇总如下,觉得不错点个Star,欢迎 加群 互相学习。
我是小智,公众号「大迁世界」作者,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!
关注公众号,后台回复福利,即可看到福利,你懂的。
附:新文章会提交发布公众号哦。
每次整理文章,一般都到2点才睡觉,一周4次左右,挺苦的,还望支持,给点鼓励
出处:https://juejin.im/post/5d48c275f265da03b12032a1
原文地址:https://www.cnblogs.com/mq0036/p/12108326.html
- Java面试系列21-xml
- tensorflow载入数据的三种方式 之 TF生成数据的方法
- JS游戏开发 可移动地图的实现
- Java面试系列-多线程
- pymongo.errors:Sort operation used more than the maximum 33554432 bytes of RAM. Add an index,
- PG学习初体验--源码安装和简单命令(r8笔记第97天)
- Pymongo: TypeError: if no direction is specified, key_or_list must be an instance of list
- Java面试系列19-Struts2
- JS游戏开发,让你的静态人物动起来(来自网路)
- Golang语言websocket源码
- 社团划分——Fast Unfolding算法
- 【PSU】AIX 11g RAC自动打GI PSU5
- 详解自动识别验证码,LSTM大显身手
- 智能算法——PageRank
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法