从枚举属性谈JS对象的遍历

最近查资料的时候发现了一些有趣的事情,主要是从Object.create这个函数中发现了一些知识漏洞,于是想梳理一下。

创建对象的简单方法大概有以下几种

function Person() {
  this.x = 5;
}
let a1 = {x: 5};
let a2 = new Person();
let a3 = Object.create({x: 5});
let a4 = Object.create({}, {
  x: 5
});

以上四种方法创建的对象均可以使用a.x访问到该对象的x属性,但其中还是有一些差别的。

  • a1是通过对象字面量创建的实例 与a1 = new Object({x: 5})创建出来的实例没有差别。

  • a2是通过构造函数创建的对象 其constructor属性指向的Person构造函数,proto属性指向的是Person构造函数的prototype。

  • a3是通过Object.create函数创建的实例,以第一个参数{x: 5}为原型对象创建的,故a3.x访问的是原型链上的x属性。

  • a4是通过Object.create函数创建的实例,以第一个参数{}为原型对象,第二个参数为属性配置创建的。

以上示例的对象不仅具有原理上的不同,在遍历中也有不同的表现。对对象的遍历我们可以想到使用for in 循环。for in循环的原理则是遍历对象及其原型链上所有的可枚举属性。

function iterator(x) {
  for(let i in x) {
    console.log(i);
  }
}
iterator(a1) // 输出x
iterator(a2) // 输出x
iterator(a3) // 输出x
iterator(a4) // 输出undefined

我们发现了a4方式创建的对象与其它3种方法在使用for in方法遍历时的不同,可以看到他的属性描述符都被置为false。

Object.getOwnPropertyDescriptor(a2,"x") // 输出 Object {value: 5, writable: false, enumerable: false, configurable: false}
  • 查阅了JavaScript权威指南后发现,如果指定可选的descriptors属性,如Object.create(p,d)等同于Object.defineProperties(Object.create(p),d)

  • 所以如果不指定描述符为true的情况下所有描述符都会默认指定为false。了解这种创建对象属性的方法很有利于设置我们遍历中不想获得的属性。

  • 另外for in 会枚举到所有原型链上的可枚举属性,解决的办法有2个
    // 第一种解决办法
    function iterator(x) {
    for(let i in x) {
    if (x.hasOwnProperty(i))
    console.log(i);
    }
    }

    // 第二种解决办法
    Object.keys(x) // 获取所有非继承的可枚举属性再for遍历
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 序 从最近的js入门系列的阅读量逐步递减,观众老爷的兴趣也不再能够接受一些细节性的地方深度挖掘,让我有了一些思考。...
    zhaolion阅读 1,645评论 5 19
  • 作者:clearbug原文地址:http://www.cnblogs.com/craftsman-gao/p/48...
    IT程序狮阅读 805评论 1 8
  • 我们都一样在恋爱时期,陷入爱河,不考虑以后,只会在乎现在。可姑娘们,你们要为自己想想,要对自己负责。吃药,堕...
    Aries晴阅读 268评论 0 0
  • 大多数人在孩童时代都应该问过家长一个问题吧,自己是从哪里来的。 妈妈说我是从煤墩里捡来的。说真的,我也像大多数孩子...
    鬼目春阅读 388评论 4 1
  • 蛰伏很久了,此夜 在做最长一次 思索后 决定从 明天开始 与漫漫长夜,一一告别 此消彼长,与日俱增 我把触手,而生...
    细雨烟岚阅读 228评论 0 0