一、前言

我们知道,在js的对象中,有下面几种属性:

  • 可枚举属性
  • 不可枚举属性
  • 从原型链上继承的属性
  • 以Symbol作为key值

今天,我们就来谈一谈如何遍历这些属性。

二、遍历可枚举属性

  首先,遍历可枚举属性是非常常见的一个需求,我们平时比较常用的方法是for in和Object.keys(),这两个方法都能遍历可枚举属性,我们看看如下的代码:

let obj = {name: "klx",sex: "man",age: 21
}Object.keys(obj).forEach((key, index) => {console.log(`${key}:${obj[key]}`);
})
//name:klx
//sex:man
//age:21
for(key in obj) {console.log(`${key}:${obj[key]}`);
}
//name:klx
//sex:man
//age:21

  可以看到,他们并没有什么区别。那么,这两个方法是完全一样的吗?我们再来看看下面的代码:

let obj = {name: "klx",sex: "man",age: 21
}let parent = {parentName: "parent",parentSex: "man",parentAge:40
}Object.setPrototypeOf(obj, parent);Object.keys(obj).forEach((key, index) => {console.log(`${key}:${obj[key]}`);
})
//name:klx
//sex:man
//age:21
for(key in obj) {console.log(`${key}:${obj[key]}`);
}
//name:klx
//sex:man
//age:21
//parentName:parent
//parentSex:man
//parentAge:40

  这时我们可以看到,第二种方法比第一种多出来几个属性。所以,他们的区别就体现出来了,我们在上面的代码中将obj的原型对象设置为了另一个对象,而for in把原型链上的属性也遍历了出来,但是Object.keys没有。所以,他们两个的区别就是:for in会遍历原型链上的属性,Object.keys不会遍历原型链上的属性。所以,我们平时最好使用Object.keys去遍历对象,会避免一些不必要的麻烦。

二、遍历不可枚举属性

  什么是不可枚举属性?如果不知道这个问题的同学可以参考MDN的介绍,这里我就不详细解释了。我们先来看看下面的代码:

let obj = {name: "klx",sex: "man",age: 21
}Object.defineProperty(obj, 'age', {enumerable:false,configurable:true,writable:true
})
Object.keys(obj).forEach((key, index) => {console.log(`${key}:${obj[key]}`);
})
//name:klx
//sex:man
for(key in obj) {console.log(`${key}:${obj[key]}`);
}
//name:klx
//sex:man

  在这里,我们把age改成了不可枚举属性(因为我们的年龄不能随便告诉别人啊~)。所以可以看见,不管我们用for in还是Object.keys都无法遍历到age属性。那么,我们这时该如何才能遍历到age这个属性呢?
  我们可以使用Object.getOwnPropertyNames()这个方法,来看下面的代码

let obj = {name: "klx",sex: "man",age: 21,
}
let a = Symbol('a');obj[a] = 'Symbol';Object.defineProperty(obj, 'age', {enumerable:false,configurable:true,writable:true
})let parent = {parentName: "parent",parentSex: "man",parentAge:40
}Object.setPrototypeOf(obj, parent);Object.keys(obj).forEach((key, index) => {console.log(`${key}:${obj[key]}`);
})
//name:klx
//sex:man
for(key in obj) {console.log(`${key}:${obj[key]}`);
}
//name:klx
//sex:man
//parentName:parent
//parentSex:man
//parentAge:40
Object.getOwnPropertyNames(obj).forEach(key => {console.log(`${key}:${obj[key]}`);
})
//name:klx
//sex:man
//age:21

  所以,使用Object.getOwnPropertyNames就能遍历到这个对象除掉以Symbol作为名称的属性,同时也不能遍历到原型链上的属性。

三、遍历以Symbol作为key值的属性

  那么,如果我们想要遍历以Symbol作为key值的属性该怎么办呢?这时我们可以用这个方法:Object.getOwnPropertySymbols。

let obj = {name: "klx",sex: "man",age: 21,
}
let a = Symbol('a');obj[a] = 'Symbol';Object.defineProperty(obj, 'age', {enumerable:false,configurable:true,writable:true
})let parent = {parentName: "parent",parentSex: "man",parentAge:40
}Object.setPrototypeOf(obj, parent);Object.keys(obj).forEach((key, index) => {console.log(`${key}:${obj[key]}`);
})
//name:klx
//sex:man
for(key in obj) {console.log(`${key}:${obj[key]}`);
}
//name:klx
//sex:man
//parentName:parent
//parentSex:man
//parentAge:40
Object.getOwnPropertyNames(obj).forEach(key => {console.log(`${key}:${obj[key]}`);
})
//name:klx
//sex:man
//age:21
Object.getOwnPropertySymbols(obj).forEach(key => {console.log(obj[key]);
})
//Symbol

  那么问题来了,如果我想遍历一个对象上的全部属性,又该怎么做呢?这时我们可以用Reflect.ownKeys()方法来达到我们的目的,他会放回该对象上的所有属性,但是不包括原型链上的属性:

let obj = {name: "klx",sex: "man",age: 21,
}
let a = Symbol('a');obj[a] = 'Symbol';Object.defineProperty(obj, 'age', {enumerable:false,configurable:true,writable:true
})let parent = {parentName: "parent",parentSex: "man",parentAge:40
}Object.setPrototypeOf(obj, parent);console.log(Reflect.ownKeys(obj));
//[ 'name', 'sex', 'age', Symbol(a) ]

四、遍历自身以及原型链上的所有属性

  那么,如果我不仅仅想遍历自身所有属性,还想遍历原型链上的所有属性,该怎么办?这时,就没有现成的api供我们调用了,但是我们可以自己写一个方法来遍历:

let obj = {name: "klx",sex: "man",age: 21,
}
let a = Symbol('a');obj[a] = 'Symbol';Object.defineProperty(obj, 'age', {enumerable:false,configurable:true,writable:true
})let parent = {parentName: "parent",parentSex: "man",parentAge:40
}Object.setPrototypeOf(obj, parent);function traverse(obj, arr) {arr.push(...Reflect.ownKeys(obj));if(Object.getPrototypeOf(obj)) {traverse(Object.getPrototypeOf(obj), arr);}return arr;
}console.log(traverse(obj, []));
/*
[ 'name','sex','age',Symbol(a),'parentName','parentSex','parentAge','constructor','__defineGetter__','__defineSetter__','hasOwnProperty','__lookupGetter__','__lookupSetter__','isPrototypeOf','propertyIsEnumerable','toString','valueOf','__proto__','toLocaleString' ]
*/

  这样,我们就把该对象以及原型链上的属性全部遍历出来了,当然,你也可以根据自己的需求,利用上述几个方法组合,来遍历自己想要的属性。

五、结语

  不要小看一个简单的问题,其中可能有许多你不知道的小知识。我们平时简单遍历一个对象可能单纯使用for in就能完成我们的工作了,但是这些更多的细节问题你有注意到吗?好了,这篇博客就到这里了,希望能带给大家一些东西~

js中遍历对象的几种方法相关推荐

  1. php 遍历对象数组,js中遍历对象(5种)和遍历数组(6种)的方法总结

    本篇文章给大家带来的内容是关于js中遍历对象(5种)和遍历数组(6种)的方法总结,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 一.遍历对象方法 1.for...in 遍历输出的是对 ...

  2. Js中访问对象的两种方法

    我们通常都使用点" . '"表示法来访问对象,在js中也可以用方括号" [ ] "来访问对象的属性. 使用[]时,应该将想要访问的属性用字符串的形式放在&quo ...

  3. js遍历对象的几种方法

    js遍历对象的几种方法 第一种: for......in const obj = {id:1,name:'zhangsan',age:18 }for(let key in obj){console.l ...

  4. JS遍历对象的七种方法

    我根据阮老师的<ES6标准入门>学习并总结了七种遍历对象的方法,我会将分别介绍这七种方法并进行详细的区分,并将从属性可枚举性问题与遍历方法两个大方面讲述全文,其中可枚举性是掌握遍历对象之前 ...

  5. jquery 遍历java对象,js/jquery遍历对象和数组的方法分析【forEach,map与each方法】...

    本文实例讲述了js/jquery遍历对象和数组的方法.分享给大家供大家参考,具体如下: JS forEach方法 arr[].forEach(function(value,index,array){ ...

  6. 【javascript基础——系列10】js中隐藏元素的几种方法以及代码

    系列文章 [javascript基础--系列1]前端页面ajax连接后台服务器传输数据 [javascript基础--系列2]前端页面axios连接后台服务器传输数据 [javascript基础--系 ...

  7. 【JS】中遍历数组的几种方法

    目录 1. for 遍历数组 1.1 for 的普通遍历 1.2 for 优化版遍历 2.while 遍历数组 3. for...in 方法 3.1 遍历数组 3.2 遍历对象 4. for...of ...

  8. java中遍历HashMap的四种方法及效率比较

    1. 推荐方法: 使用entrySet 遍历Map 类集合KV,而不是keySet 方式进行遍历. 代码示例如下: // 循环第二种HashMap<Integer, String> map ...

  9. Js中数组去重的几种方法

    前几天在看前端面试题的时候,其中js部分有个问题是实现数组去重的算法,一开始就想了一两种方法,后来仔细回忆了下这个题,觉得该问题实现方法确实不止局限于一两种方法 ,从不同的角度去看待该问题就会有多种实 ...

最新文章

  1. iclone7.8中文版
  2. 判断触发器正在处理的是插入,删除还是更新触发
  3. wxWidgets:wxBitmapToggleButton类用法
  4. IBASE handle free after save - buffer table cleared
  5. ArcGIS实验教程——实验八:矢量数据拼接
  6. python手枪_Python入门,爬虫训练——枪械查询
  7. php class类 教程,PHP类(Class)入门教程第2/2页
  8. 作者:梁永生(1971-),男,博士,深圳信息职业技术学院教授,广东省珠江学者特聘教授,《大数据》深圳市大数据发展动态调研组组长...
  9. Ethercat解析(十一)之分布时钟
  10. DaNet: Decompose-and-aggregate Network for 3D Human Shape and Pose Estimation
  11. sql中的distinct
  12. Hibernate之集合映射
  13. 高通平台SPI驱动框架分析
  14. PMP考试提分必刷题
  15. 浙江计算机三级在线试题及答案,计算机三级试题及答案
  16. Aqua Comms携手Ciena 测试海底光缆网络150Gbps波长传输
  17. 相对传统桌面设计器,在线报表设计器价值何在?
  18. idea怎么进行c语言编程_idea编写c语言
  19. 埃森哲 X SAP:智慧转型高手论剑
  20. 成都学python哪个机构好_成都学python人工智能哪个机构好

热门文章

  1. react map遍历
  2. 支付宝 error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag
  3. 电脑诊断出策略服务器未运行,win10系统使用诊断策略服务提示未运行的具体技巧...
  4. 计算机助学教学软件cai是,小学语文教学设计 [用教学设计理论指导CAI软件设计]...
  5. ELKstack日志收集系统
  6. Java迭代器 for循环的区别
  7. iframe跨域sessionid问题
  8. centos sftp客户端 c 源码_如何在 Linux 系统中如何更改 SFTP 端口
  9. 科比罚篮,武器命中和霍金劫数
  10. GitFlow详解教程