你不知道的js对象遍历

2,450 阅读3分钟

前言

js里面遍历一个对象的属性有很多种方式,比如:Object.keysfor...inObject.getOwnPropertyNames等等,平时写业务代码的时候,大家随便用哪个。 可是它们之间的区别,我相信,大部分(不是所有,此处狗头🐶保命)前端小伙伴应该都不太清楚

属性的可枚举性

可枚举属性

通常我们给对象定义、或者新增一个属性的方式基本如下

let obj = { a: 1 }
obj.b = 2

上面代码给obj对象添加了ab两个属性,这两个属性都是可枚举

不可枚举属性

那么怎么让添加的属性不可枚举呢,见如下代码

Object.defineProperty(obj,'c',{
  enumerable: false,
  value: 3
})

上面代码,又给obj添加了一个c属性,此时c属性就是不可枚举的。关键就是enumerable: false这句代码,如果不特别给enumerable赋值成false,那么默认都是可枚举的

如何判断

判断对象中的某个属性是否可枚举,js有提供原生的propertyIsEnumerable方法

obj.propertyIsEnumerable('a')   // true
obj.propertyIsEnumerable('b')   // true
obj.propertyIsEnumerable('c')   // false

上面代码执行的结果符合预期,只有c是不可枚举的

原型链属性

有的属性不是直接存在于对象中,而是存在于对象的原型链中

添加原型链属性

Object.prototype.d = 4

上面代码,给Object的原型链添加了一个属性d。此时d没有直接存在于obj中,而是存在于obj的原型链上

如何判断

in

通常我们会直接用in来判断某个属性是不是存在某个对象中

'a' in obj   // true
'b' in obj   // true
'c' in obj   // true
'd' in obj   // true

上面结果表明in操作符会检查属性是否在对象以及其原型链中

hasOwnProperty

hasOwnProperty也可以来判断属性是否在对象中

obj.hasOwnProperty('a')     // true
obj.hasOwnProperty('b')     // true
obj.hasOwnProperty('c')     // true
obj.hasOwnProperty('d')     // false

in对比一下,大家可以看出差别,obj.hasOwnProperty('d')的结果是false,而d是添加在原型链中的属性,所以hasOwnProperty只会检查属性是否在对象本身,而不会去检查是否在原型链中

两者结合

所以结合inhasOwnProperty我们就可以知道某个属性是直接在对象中,还是在对象的原型链中

'd' in obj && !obj.hasOwnProperty('d')   // true  (属性在原型链中)

对象遍历

通过上面的介绍,大家应该也猜测到,Object.keysfor...inObject.getOwnPropertyNames的区别其实就在于能否遍历对象的可枚举属性,以及能否遍历原型链上的属性

for...in

首先说下for...in,执行如下代码

for(let key in obj){
   console.log(key)
}
// a
// b
// d

打印出了abd三个属性,c没有打印出来,所以for...in只会遍历对象本身的、以及原型链上的所有可枚举属性

Object.keys

执行如下代码

Object.keys(obj)
// ["a", "b"]

打印出了ab两个属性,cd没有打印出来,所以Object.keys只会遍历对象本身的可枚举属性,不会遍历原型链上的属性

Object.getOwnPropertyNames

执行如下代码

Object.getOwnPropertyNames(obj)
// ["a", "b", "c"]

打印出了abc三个属性,没有打印出d,所以Object.getOwnPropertyNames只会遍历对象本身的所有属性,包括不可枚举属性,不会遍历原型链上的属性

总结

上面的内容是我看 《你不知道Javascript(上卷)》 第三章对象遍历 部分总结出来的东西,如有疑问,欢迎在评论区留言