JavaScript куча нехватки памяти при цикле по карте? - PullRequest
0 голосов
/ 06 ноября 2018
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)

Приведенный выше код при запуске с использованием узла возвращает следующую ошибку -

ФАТАЛЬНАЯ ОШИБКА: неэффективные компактные метки вблизи предельного значения кучи не удалось - куча JavaScript из памяти 1: 0x100037ddb node :: Abort () [/ USR / местные / бен / узел]

Может кто-нибудь объяснить причину? карта создается просто отлично. Только когда я перебираю ключи 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 голосов
/ 06 ноября 2018

Проблема в том, что ваши ключи - это строки, а не цифры. Вам нужно вызвать parseInt () или Number () для их преобразования перед добавлением:

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

Цикл все еще займет много времени (вы повторяете 10 ** 10 раз), но вы не накопите огромную строку, которая взрывает использование памяти.

ОБНОВЛЕНИЕ: уступил первенству использования Number () вместо parseInt ().

0 голосов
/ 06 ноября 2018

Причина, о которой говорилось в принятом ответе, заключалась в том, что я добавлял строки. Но также преобразование из строки в int является дорогостоящей операцией, особенно если зацикливаться на таком большом количестве чисел, это займет вечность.

Так что для кого-то еще, кто читает этот вопрос и должен использовать карту, можно использовать Javascript Карта вместо Объект , как используется в моем примере выше, потому что Карта может поддерживать любой тип ключа (не только строки) . Так что код для этого будет -

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)
0 голосов
/ 06 ноября 2018

при использовании for..in вы перебираете все перечисляемые свойства, включая унаследованные в цепочке прототипов (так что для объекта их довольно много )

вам нужно оградить свой цикл от унаследованных реквизитов с помощью hasOwnProperty, как это указано , описанное в примере на MDN

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...