资讯专栏INFORMATION COLUMN

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

isLishude / 666人阅读

摘要:当普通对象要转换成时就很有用,因为返回的格式与构造函数接受的格式完全相同。使用常规的构造函数可以将一个二维键值对数组转换成一个对象。在和早期标准中,根本没有指定属性的顺序。此函数还可以轻松地将纯对象属性映射到对象中。

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

想阅读更多优质文章请猛戳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()返回一个与数组解构赋值兼容的集合,因此不需要为赋值或声明添加额外的行。

当普通对象要转换成 MapObject.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.getOwnPropertyNamesReflect.ownKeys来编写示例讲解这一属性排序规则。

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

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

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

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

总结

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

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

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

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

交流

干货系列文章汇总如下,觉得不错点个Star,欢迎 加群 互相学习。

https://github.com/qq44924588...

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

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

附:新文章会提交发布公众号哦。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106417.html

相关文章

  • 关于 express 路由管理几种自动化方法

    摘要:在方法装饰器的编写上,由于装饰器的行为相似,因此我们可以编写一个抽象函数,用来生成不同请求方法的不同装饰器。文章博客地址关于路由管理的几种自动化方法 前言 我们平时在使用express写代码的过程中,会根据类别,将路由分为多个不同的文件,然后在项目的入口文件(例如app.js)中将其依次挂载,例如: const index = require(./routes/index) const...

    chaosx110 评论0 收藏0
  • 循环几种类型

    摘要:返回值方法创建一个新数组其包含通过所提供函数实现的测试的所有元素。如果数组中的每个元素都满足测试函数,则返回,否则返回。 showImg(https://segmentfault.com/img/bVXxkh?w=700&h=700);循环遍历数组的时候,你还在用for语句走天下吗? 我曾经就是for走天下,最后发现自己给自己挖了一个巨大的坑,层层嵌套的循环,总要花大量的时间去捋清各种...

    yibinnn 评论0 收藏0
  • 循环几种类型

    摘要:返回值方法创建一个新数组其包含通过所提供函数实现的测试的所有元素。如果数组中的每个元素都满足测试函数,则返回,否则返回。 showImg(https://segmentfault.com/img/bVXxkh?w=700&h=700);循环遍历数组的时候,你还在用for语句走天下吗? 我曾经就是for走天下,最后发现自己给自己挖了一个巨大的坑,层层嵌套的循环,总要花大量的时间去捋清各种...

    clasnake 评论0 收藏0
  • 循环几种类型

    摘要:返回值方法创建一个新数组其包含通过所提供函数实现的测试的所有元素。如果数组中的每个元素都满足测试函数,则返回,否则返回。 showImg(https://segmentfault.com/img/bVXxkh?w=700&h=700);循环遍历数组的时候,你还在用for语句走天下吗? 我曾经就是for走天下,最后发现自己给自己挖了一个巨大的坑,层层嵌套的循环,总要花大量的时间去捋清各种...

    HtmlCssJs 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<