我们从一个很简单的问题出发,怎么遍历一个 js 对象?第一种使用 forin,但是会遍历到原型链上的属性,这个不是我们想要的。
forin 存在的问题
var s = {a:1}
s.__proto__ = {b:2}
for(var i in s) {console.log(i)}
所以我们要这样判断一下。
var s = {a:1}
s.__proto__ = {b:2}
for(var i in s) { if(s.hasOwnProperty(i)) console.log(i)}
Object.entries 会更慢
如果不想使用 hasOwnProperty,可以使用 Object.entries
。
var s = {a:1}
s.__proto__ = {b:2}
for(var [k,v] of Object.entries(s)) { console.log(k)}
Object.entries 会比 forin 效率要低,但是低多少呢?我们看看下面的例子。
let data = {}
let length = 10 ** 6
let i = 0
let map = new Map()
for (; i < length; i += 1) {
data[i] = i
map.set(i,i)
}
console.time('forin')
for(let key in data){
if(data.hasOwnProperty(key)){
let value = data[key]
// silence
}
}
console.timeEnd('forin')
console.time('entries')
let arr = Object.entries(data)
for(let [k, v] of arr){
// silence
}
console.timeEnd('entries')
console.time('Map')
for(let [k, v] of map){
// silence
}
console.timeEnd('Map')
似乎使用 Map 更好
2020-02-25 更新:
再看一下上面的例子,使用 Map,既不用做原型链属性的检测,也能更快的遍历。Map 是经过优化的,更应该推荐这种写法,或者说使用这种数据结构。
总结
在我机器上,Object.entries 的运行时间会比 forin 多 2-3 倍的时间,所以特别、极度、十分注重效率的话用 forin,否则的话代码更优雅一点。