几天前一个小伙伴问我 Object.getOwnPropertyNames() 是干什么用的

平时还真没有使用到这个方法,一时不知如何回答

从方法名称来分析,应该是返回的是对象自身属性名组成的数组

那和 Object.keys() 方法不就一样了吗

感觉事情并不这么简单,于是我仔细看了一下这几种遍历对象的方法的区别

for in

for in 循环是最基础的遍历对象的方式,它还会得到对象原型链上的属性

// 创建一个对象并指定其原型,bar 为原型上的属性
const obj = Object.create({
bar: 'bar'
}) // foo 为对象自身的属性
obj.foo = 'foo' for (let key in obj) {
console.log(obj[key]) // foo, bar
}

可以看到对象原型上的属性也被循环出来了

在这种情况下可以使用对象的 hasOwnProperty() 方法过滤掉原型链上的属性

for (let key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(obj[key]) // foo
}
}

这时候原型上的 bar 属性就被过滤掉了

Object.keys

Object.keys() 是 ES5 新增的一个对象方法,该方法返回对象自身属性名组成的数组,它会自动过滤掉原型链上的属性,然后可以通过数组的 forEach() 方法来遍历

Object.keys(obj).forEach((key) => {
console.log(obj[key]) // foo
})

另外还有 Object.values() 方法和 Object.entries() 方法,这两方法的作用范围和 Object.keys() 方法类似,因此不再说明

for in 循环和 Object.keys() 方法都不会返回对象的不可枚举属性

如果需要遍历不可枚举的属性,就要用到前面提到的 Object.getOwnPropertyNames() 方法了

Object.getOwnPropertyNames

Object.getOwnPropertyNames() 也是 ES5 新增的一个对象方法,该方法返回对象自身属性名组成的数组,包括不可枚举的属性,也可以通过数组的 forEach 方法来遍历

// 创建一个对象并指定其原型,bar 为原型上的属性
// baz 为对象自身的属性并且不可枚举
const obj = Object.create({
bar: 'bar'
}, {
baz: {
value: 'baz',
enumerable: false
}
}) obj.foo = 'foo' // 不包括不可枚举的 baz 属性
Object.keys(obj).forEach((key) => {
console.log(obj[key]) // foo
}) // 包括不可枚举的 baz 属性
Object.getOwnPropertyNames(obj).forEach((key) => {
console.log(obj[key]) // baz, foo
})

ES2015 新增了 Symbol 数据类型,该类型可以作为对象的键,针对该类型 ES2015 同样新增了 Object.getOwnPropertySymbols() 方法

Object.getOwnPropertySymbols

Object.getOwnPropertySymbols() 方法返回对象自身的 Symbol 属性组成的数组,不包括字符串属性

Object.getOwnPropertySymbols(obj).forEach((key) => {
console.log(obj[key])
})

什么都没有,因为该对象还没有 Symbol 属性

// 给对象添加一个不可枚举的 Symbol 属性
Object.defineProperties(obj, {
[Symbol('baz')]: {
value: 'Symbol baz',
enumerable: false
}
}) // 给对象添加一个可枚举的 Symbol 属性
obj[Symbol('foo')] = 'Symbol foo' Object.getOwnPropertySymbols(obj).forEach((key) => {
console.log(obj[key]) // Symbol baz, Symbol foo
})

Reflect.ownKeys

Reflect.ownKeys() 方法是 ES2015 新增的静态方法,该方法返回对象自身所有属性名组成的数组,包括不可枚举的属性和 Symbol 属性

Reflect.ownKeys(obj).forEach((key) => {
console.log(obj[key]) // baz, foo, Symbol baz, Symbol foo
})

对比

方式 基本属性 原型链 不可枚举 Symbol
for in
Object.keys()
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Reflect.ownKeys()

结论

这其中只有 for in 循环会得到对象原型链上的属性,其它方法都只适用于对象自身的属性

ES 语言后续添加的新特性不会对以前的代码产生副作用,比如在 ES2015 之前就存在的 for in 循环,Object.keys() 和 Object.getOwnPropertyNames() 是肯定不会返回 Symbol 属性的

JS遍历对象的几种方法的更多相关文章

  1. js遍历对象的属性和方法

    js遍历对象的属性和方法 一.总结 二.实例 练习1:具有默认值的构造函数 实例描述: 有时候在创建对象时候,我们希望某些属性具有默认值 案例思路: 在构造函数中判断参数值是否为undefined,如 ...

  2. js es6遍历对象的6种方法(应用中推荐前三种)

        javaScript遍历对象总结 1.for … in 循环遍历对象自身的和继承的可枚举属性(循环遍历对象自身的和继承的可枚举属性(不含Symbol属性).). 2.使用Object.keys ...

  3. 【Javascript】JS遍历数组的三种方法:map、forEach、filter

    前言 近一段时间,因为项目原因,会经常在前端对数组进行遍历.处理,JS自带的遍历方法有很多种,往往不加留意,就可能导致知识混乱的现象,并且其中还存在一些坑.前端时间在ediary中总结了js原生自带的 ...

  4. 辨析js遍历对象与数组的方法

    1     遍历对象的方法? (1) for-in(也可遍历数组,但效率较低,一般用来遍历对象) 示例: // 生成一个原型上有属性并且有可枚举属性与不可枚举属性的对象 const data = Ob ...

  5. javascript生成对象的三种方法

    /** js生成对象的三种方法*/ // 1.通过new Object,然后添加属性 示例如下: var people1 = new Object(); people1.name = 'xiaohai ...

  6. (转载)Java中如何遍历Map对象的4种方法

    在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...

  7. js定义对象的几种容易犯的错误

    //js定义对象的几种容易犯的错误function Person() { getName = function (){ console.info(1); }; return this;}//Perso ...

  8. 转载:遍历Map的四种方法

    http://www.cnblogs.com/kristain/articles/2033566.html 遍历Map的四种方法 public static void main(String[] ar ...

  9. Java反射 - 1(得到类对象的几种方法,调用方法,得到包下的所有类)

    通过反射获得对象的方法 准备工作: 有一个User类如下 package o1; /** * Created by yesiming on 16-11-19. */ public class User ...

随机推荐

  1. Map,HashMap五种遍历方法

    假设有数组            HashMap<Integer, String> h=new HashMap<Integer,String>();        h.put( ...

  2. 痞子衡嵌入式:MCUBootUtility v2.3发布,这次不再放过任何一款Flash

    -- 痞子衡的 NXP-MCUBootUtility 开源项目自2018年8月27日第一笔提交至今已有21个月,目前累计代码已近50000行.相信这个工具为大家开发 i.MXRT 项目提供了一些便利, ...

  3. 【Java8新特性】面试官:谈谈Java8中的Stream API有哪些终止操作?

    写在前面 如果你出去面试,面试官问了你关于Java8 Stream API的一些问题,比如:Java8中创建Stream流有哪几种方式?(可以参见:<[Java8新特性]面试官问我:Java8中 ...

  4. 【Ubuntu】Ubuntu18.04通过重装系统成功安装显卡驱动

    0. 前言 前面用了一天的时间来解决Ubuntu安装显卡驱动出现的用户输入密码登录后出现的紫屏.循环登录的问题,过程可阅读“[Ubuntu]Ubuntu系统启动过程中,输入用户名与密码后登录一直卡在紫 ...

  5. 【Ubuntu】安装Ubuntu18.04.2LTS

    环境:win10专业版.联想30D9主板 ubuntu:18.04.2LTS:Ubuntu镜像传送门:https://ubuntu.com/download/desktop 有两块硬盘,win10安装 ...

  6. nodejs安装及环境变量的配置

    首先,nodejs安装到C盘的 建议安装到其他盘里,这是为了防止电脑出故障后C盘下载的东西会缺失 第一次安装nodejs的,第一步打开“nodejs官网:https://nodejs.org/zh-c ...

  7. nginx 搭建图片服务器(windows 下,linux 下原理应该一样)

    作者的心声:很多知道的.用过的东西,不写下来,下次还要百度查询,浪费时间和精力,故本次写下学习笔记,方便下次查阅. 题外话:如有读者通过我这篇博客解决了工作上的难题,可以给个评论,让我一起分享你的喜悦 ...

  8. (Java实现) 洛谷 P1553 数字反转(升级版)

    题目描述 给定一个数,请将该数各个位上数字反转得到一个新数. 这次与NOIp2011普及组第一题不同的是:这个数可以是小数,分数,百分数,整数.整数反转是将所有数位对调:小数反转是把整数部分的数反转, ...

  9. Java实现 LeetCode 458 可怜的小猪

    458. 可怜的小猪 有 1000 只水桶,其中有且只有一桶装的含有毒药,其余装的都是水.它们从外观看起来都一样.如果小猪喝了毒药,它会在 15 分钟内死去. 问题来了,如果需要你在一小时内,弄清楚哪 ...

  10. Java实现 蓝桥杯VIP 算法训练 开心的金明

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过NN元钱 ...