遍历地图时JavaScript堆满了内存吗?

时间:2018-11-06 18:38:27

标签: javascript node.js dictionary

const map = {}

for (let i=0;i<10**5;i++) {
    map[i] = true
}


let ans = 0

for (let i in map) {
    for (let j in map) {
        ans += i+j
    }
}


console.log(ans)

使用 node 运行时,以上代码返回以下错误-

  

致命错误:接近堆限制分配的无效标记压缩   失败-JavaScript堆内存不足1:0x100037ddb node :: Abort()   [/ usr / local / bin / node]

有人可以解释原因吗?实例化 map 就好了。只有当我遍历 map 键并将它们添加到我的 ans 变量中时,才会遇到此问题吗?

但是,以下类似代码可以正常工作并打印 ans -

let ans = 0

for (let i=0;i<10**5;i++) {
    for (let j=0;j<10**5;j++) {
        ans += i+j
    }
}

console.log(ans)

这背后的逻辑是什么。为什么循环映射键太糟糕了?

  

节点版本v10.7.0

3 个答案:

答案 0 :(得分:6)

问题在于您的密钥是字符串,而不是数字。添加之前,您需要调用parseInt()或Number()进行转换:

for (let i in map) {
    for (let j in map) {
        ans += Number(i) + Number(j)
    }
}

循环仍会花费很长时间(您要迭代10 ** 10次),但是您不会积累一个巨大的字符串来消耗内存。

更新:屈从于使用Number()代替parseInt()。

答案 1 :(得分:0)

使用for..in时,您要遍历所有可枚举的属性,包括原型链上的继承属性(对于对象,there are quite a few

您需要使用hasOwnProperty保护循环,使其不受outlined in the example on MDN的影响,因为React Docs Hooks Proposal FAQ

答案 2 :(得分:0)

接受的答案中提到的原因是我正在添加字符串。但是从字符串转换为int也是一项昂贵的操作,特别是在循环处理如此大量的数字时,这将永远花费。

因此对于正在阅读此问题且必须使用map的其他人,可以使用Javascript Map 代替上面示例中使用的 Object ,因为 Map可以支持任何类型的键(不仅限于字符串)。因此,该代码为-

const map = new Map()

for (let i=0;i<10**5;i++) {
    map.set(i, true)
}

let ans = 0

for (const i of map.keys()) {
    for (const j of map.keys()) {
        ans += i + j
    }
}


console.log(ans)