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
答案 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)