2016-09-03 3 views
0

У меня есть этот фрагмент кода; Он в основном подключается к базе данных mongo и проходит через документы. На каждой итерации он ищет массив сообщений. Он создает переменную сообщений, а затем проходит через нее. Описанная переменная (var msg) внутри функции обратного вызова остается в памяти или она уничтожена после завершения функции обратного вызова? Будет ли какая-либо разница, если var msg был фактически объявлен как let msg? Есть ли способ отбросить всю область памяти?Сохраняются ли переменные, объявленные внутри функций обратного вызова, в памяти или уничтожаются после завершения обратного вызова?

MongoClient.connect(mongoUrl, (err, db) => { 
    assert.equal(null,err); 
    var collection_data = db.collection('threadContents').find(); 
    collection_data.on('data', (doc) => { 
    var msg = doc.messages; 
    for (var variable in msg) { 
     console.log(msg); 
    }//forin(msg) 
    });//collection_data.on 
});//mongo.connect 
+0

'это уничтожено после завершения функции функции обратного вызова?' - часто это так, это действительно зависит от кода –

+0

@JaromandaX Я предоставил образец фрагмента кода. В противном случае рекомендуется использовать способ принудительного разрушения переменной после завершения функции обратного вызова? – Kunok

+0

О, вы спрашиваете о своем конкретном коде? с какой переменной вы связаны? –

ответ

1

В теории - да.
На практике - это не так просто ...

В вашем примере, var msg не «утечка» за пределами его первоначальная масштабы, так что, скорее всего, разрушаться, когда обратный вызов завершает свою работу.
Одна вещь, которую следует отметить - уничтожение этого объекта не обязательно должно произойти сразу - JS Engines - это в основном сбор мусора, поэтому этот кусок памяти может оставаться в стеке на некоторое время, но он больше не будет доступен.

Если вы объявите эту переменную во внешней области видимости, она может остаться в памяти, если эта область осталась в памяти (поэтому другие части кода могли получить доступ к этой переменной). Вы можете прочитать об этом поведении в разделе Closures в MDN.

Еще одно примечание - использование console.log. В общем случае непримитивные значения (например, объекты или массивы, которые фактически являются «специальными» объектами), будут доступны по ссылке, а не по значению. Поэтому, если ваш var msg является непримитивным, он, скорее всего, сохранится в памяти, пока вы не очистите консоль. Примитивные значения будут скопированы, поэтому, строго говоря, они все еще сохраняются в памяти, но, вероятно, в другом месте в памяти (хотя JIT-двигатели, вероятно, могут попытаться оптимизировать это и не копировать память, если это не обязательно).

+0

Что именно вы имеете в виду, когда говорите «Очистите консоль?« – Kunok

+0

Нажмите кнопку« clear »в консоли, конечно :) – mdziekon

+0

Я фактически запускаю скрипты узлов из терминала, и такой опции нет, и от этого я не хочу зависеть, так как я стараюсь использовать наименее возможный RAM для моего скрипта, который должен выполнять действительно тяжелую работу на не очень мощном оборудовании, и я запускаю эти сценарии как задания CRON. – Kunok

1

Node.js (и все javascript-двигатели) полагаются на tracing garbage collection, что означает, что выделенная память освобождается недетерминированным способом, т. Е. Вы не можете точно предсказать, когда это произойдет. Это обычно не влияет на вас, но если вы действительно хотите, чтобы какой-то фрагмент памяти или какой-либо другой ресурс был освобожден предсказуемым образом, вам нужно использовать специальную технику.

0

В вашем конкретном примере «msg» будет удален, но не ожидайте, что он будет удален сразу.

+0

На каком событии JavaScript удалит его позже (не сразу)? – Kunok

+0

Я имел в виду, что не предсказуемо говорить, когда это произойдет. – snit80

+0

Есть ли какой-либо документ связанных с этим? – Kunok

Смежные вопросы