这个总结是有感而发。话不多说

如果一个对象上具有某个属性,但这个属性:

  • 设置了 enumerable:false,无法迭代
  • key属于Symbol,无法迭代
  • key继承自原型链上,自定义内容可以迭代

就需要注意了。举个例子

  1. var Fun= function(){}
  2. Fun.prototype.protoFun=function(){return 'hh'} // 设置原型链
  3. var aa= new Fun()
  4. aa.selfAttr=1
  5. let symbolKey = Symbol('c')
  6. aa[symbolKey]=3
  7. Object.defineProperty(aa,'enum',{value:'fff',enumerable:false})
  8. // 此时 刚才提到的需要注意的点都有了
  9. aa.protoFun
  10. aa.selfAttr
  11. aa[symbolKey]
  12. aa.enum

一定要拿 xxx.hasOwnProperty(key)做判断

迭代操作:

自身 不可枚举 Symbol 原型链
for…in
Object.getOwnPropertyNames
Object.keys
Object.getOwnPropertySymbols()
Reflect.ownKeys

注意for…in 和 Object.keys 的区别,如果只是迭代对象普通属性,更推荐 Object.keys(o) ,再配合 for...of 完成迭代。

访问操作:

  1. var o ={x:1}
  2. 'x' in o //true
  3. // 但能找到原型链
  4. 'toString' in o //true
  5. o.hasOwnProperty('x') // true
  6. // 只能看自身的
  7. o.hasOwnProperty('toString')// false
  • in
  • o.hasOwnProperty('x')

    for…in

for…in语句以任意顺序遍历一个对象的除Symbol以外的可枚举属性。 — MDN for…in

  1. for(let i in aa){console.log(i,aa[i])}

这里打印的只有 普通属性b,和继承的属性 hh

需要注意了:

  • 没有 Symbol
  • 没有不可枚举属性

Object.getOwnPropertyNames()

获取对象所有自身属性的属性名,返回数组

  • 包含不可枚举
  • 不包含 Symbol

MDN Object.getOwnPropertyNames()

  1. Object.getOwnPropertyNames(aa) // ["b", "enum"]

比 for…in 好了一点点

Object.key()

  1. Object.keys(aa) // ["b"]

没有原型链、没有不可枚举、没有symbol

Object.getOwnPropertySymbols()

仅 symbol

Reflect.ownKeys()

返回数组,包含目标自身的属性

等同于

  1. Reflect.ownKeys //等同于下面
  2. Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
  3. [...Object.getOwnPropertyNames(target),...Object.getOwnPropertySymbols(target)]

for…of

for…of 逃不过,这里展开汇总
它是 es6 新增的内容。本质上和 for…in 完全不同。of专门用于 可迭代对象 ,比如 数组、字符串、set/map 是可迭代的。但对象不是。

迭代过程是实时的,也就是如果迭代过程对数据有影响,比如对数组push,会影响下一次执行。