这个总结是有感而发。话不多说
如果一个对象上具有某个属性,但这个属性:
- 设置了 enumerable:false,无法迭代
- key属于Symbol,无法迭代
- key继承自原型链上,自定义内容可以迭代
就需要注意了。举个例子
var Fun= function(){}
Fun.prototype.protoFun=function(){return 'hh'} // 设置原型链
var aa= new Fun()
aa.selfAttr=1
let symbolKey = Symbol('c')
aa[symbolKey]=3
Object.defineProperty(aa,'enum',{value:'fff',enumerable:false})
// 此时 刚才提到的需要注意的点都有了
aa.protoFun
aa.selfAttr
aa[symbolKey]
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
完成迭代。
访问操作:
var o ={x:1}
'x' in o //true
// 但能找到原型链
'toString' in o //true
o.hasOwnProperty('x') // true
// 只能看自身的
o.hasOwnProperty('toString')// false
for…in语句以任意顺序遍历一个对象的除Symbol以外的可枚举属性。 — MDN for…in
for(let i in aa){console.log(i,aa[i])}
这里打印的只有 普通属性b,和继承的属性 hh
需要注意了:
- 没有 Symbol
- 没有不可枚举属性
Object.getOwnPropertyNames()
获取对象所有自身属性的属性名,返回数组
- 包含不可枚举
- 不包含 Symbol
MDN Object.getOwnPropertyNames()
Object.getOwnPropertyNames(aa) // ["b", "enum"]
比 for…in 好了一点点
Object.key()
Object.keys(aa) // ["b"]
没有原型链、没有不可枚举、没有symbol
Object.getOwnPropertySymbols()
仅 symbol
Reflect.ownKeys()
返回数组,包含目标自身的属性
等同于
Reflect.ownKeys //等同于下面
Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
[...Object.getOwnPropertyNames(target),...Object.getOwnPropertySymbols(target)]
for…of
for…of 逃不过,这里展开汇总
它是 es6 新增的内容。本质上和 for…in 完全不同。of专门用于 可迭代对象 ,比如 数组、字符串、set/map 是可迭代的。但对象不是。
迭代过程是实时的,也就是如果迭代过程对数据有影响,比如对数组push,会影响下一次执行。