几天前一个小伙伴问我 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. 玩转Nginx location配置

    原文链接:https://mp.weixin.qq.com/s/kaEtfmX9bVdKfCVY6gbOsQ 建议点击原文链接查看 nginx是一个跨平台的web服务器, 基于事件驱动的架构并发处理百 ...

  2. 查看包名和Activity的小工具

    添加到右键菜单,很方便. 做个记录:请移步原文

  3. HTTP 规范中的那些暗坑

    HTTP 协议可以说是开发者最熟悉的一个网络协议,「简单易懂」和「易于扩展」两个特点让它成为应用最广泛的应用层协议. 虽然有诸多的优点,但是在协议定义时因为诸多的博弈和限制,还是隐藏了不少暗坑,让人一 ...

  4. 小智的糖果(Candy) 51nod 提高组试题

    luogu AC通道! (官方数据) 题目描述 小智家里来了很多的朋友,总共有N个人,站成一排,分别编号为0到N-1,小智要给他们分糖果.但 是有的朋友有一些特殊的要求,有的人要求他左右的两个人(左边 ...

  5. 实现一个 $attr(name,value) 遍历;属性为 name 值为 value 的元素集合

    <body> <div class="box clearfix"></div> <div name="zs">& ...

  6. Java实现 蓝桥杯 算法提高 天天向上(DP)

    试题 算法提高 天天向上 问题描述 A同学的学习成绩十分不稳定,于是老师对他说:"只要你连续4天成绩有进步,那我就奖励给你一朵小红花."可是这对于A同学太困难了.于是,老师对他放宽 ...

  7. Java实现 LeetCode 8 字符串转换整数(atoi)

    8. 字符串转换整数 (atoi) 请你来实现一个 atoi 函数,使其能将字符串转换成整数. 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止. 当我们寻找到的第一个非 ...

  8. Java实现 洛谷 P2089 烤鸡

    import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.Sc ...

  9. PAT 统计同成绩学生

    本题要求读入 N 名学生的成绩,将获得某一给定分数的学生人数输出. 输入格式: 输入在第 1 行给出不超过 105 的正整数 N,即学生总人数.随后一行给出 N 名学生的百分制整数成绩,中间以空格分隔 ...

  10. 性能测试中TPS上不去的原因

    TPS(Transaction Per Second):每秒事务数,指服务器在单位时间内(秒)可以处理的事务数量,一般以request/second为单位. 压测中为什么TPS上不去的原因: .网络带 ...