Когда объекты JavaScript уничтожаются?
В С++ я могу определить конструктор и деструктор явно, а затем cout < "C или D вызывается" из функции конструктора/деструктора, чтобы точно знать, где.
Однако в JavaScript как узнать, когда объект разрушен. Ниже приведен пример, который касается меня.
Я вызываю внутреннюю функцию в тайм-аут, и мне интересно, остается ли объект в живых до тех пор, пока работает таймер, ожидая повторного вызова снова.
Пользовательские звонки Контроль
// Calls Control
Управление вызовами Сообщение
var message_object = new Message( response_element );
Вызов сообщений Эффекты
new Effects().fade( this.element, 'down', 4000 );
message_object.display( 'empty' );
Эффекты
/**
*Effects - build out as needed
* element - holds the element to fade
* direction - determines which way to fade the element
* max_time - length of the fade
*/
var Effects = function( )
{
this.fade = function( element, direction, max_time )
{
element.elapsed = 0;
clearTimeout( element.timeout_id );
function next()
{
element.elapsed += 10;
if ( direction === 'up' )
{
element.style.opacity = element.elapsed / max_time;
}
else if ( direction === 'down' )
{
element.style.opacity = ( max_time - element.elapsed ) / max_time;
}
if ( element.elapsed <= max_time )
{
element.timeout_id = setTimeout( next, 10 );
}
}
next();
}
};
Ответы
Ответ 1
Объекты JS не имеют деструкторов как таковые.
Объекты JavaScript (и примитивы) - это сбор мусора, когда они становятся недоступными, что означает отсутствие ссылки на них в текущем контексте выполнения. Время выполнения JavaScript для этого постоянно отслеживается. Поэтому, если вы не используете ключевое слово delete
, чтобы удалить что-то, то его разрушение под капотом. Некоторые браузеры плохо обнаруживают ссылки, оставшиеся в области закрытия (я смотрю на вас, Редмонд), и поэтому вы часто видите, что объекты, которые были установлены в нуль в конце функций, - чтобы убедиться, что память освобождена в IE.
Ответ 2
Это представление о том, что уничтожение объекта сводится к сборке мусора для памяти, поражает меня как опасное введение в заблуждение, так как проблема не сводится к освобождению памяти.
Деструкторы несут ответственность за освобождение других ресурсов, таких как дескрипторы файлов или прослушиватели событий, которые автоматически не обрабатываются сбором мусора. В таких случаях деструкторы абсолютно необходимы для разматывания состояния до освобождения памяти или утечки ресурсов.
В таких случаях проблема заключается в том, что деструкторы не являются первоклассным понятием, нужно ли их явно называть или их можно назвать неявно после того, как объект становится недоступным.
Лучший способ справиться с этим - правильно документировать ваши модули, если им нужны деструкторы, которые будут использоваться, и подчеркивать сценарии утечки ресурсов, которые не могут использоваться таким образом.
Ответ 3
В ECMAscript отсутствует управление динамической памятью. Сборщик мусора позаботится о том, что требует памяти в вашем script. Поэтому на самом деле вопрос должен быть более похож,
"Как знает сборщик мусора, когда он может освобождать память для объектов"
Проще говоря, большинство GC смотрят, есть ли какие-либо активные ссылки. Это может быть связано с родительским контекстным объектом, цепочками прототипов или любым прямым доступом к данному объекту. В вашем конкретном случае в любое время setTimeout
выполняется выполнение, он вызывает next()
, который закрывается в родительском контексте .fade()
, а функция .face()
, в свою очередь, закрывает функцию Effects
(контекст).
Это означает, что до тех пор, пока есть вызовы setTimeout
, вся целая конструкция хранится в памяти.
Вы можете иногда помогать старым реализациям GC, используя null
переменные переменные/ссылки на них, которые могут собирать некоторые вещи раньше или вообще, но современные реализации довольно умен в этом отношении. На самом деле вам не нужно заботиться о таких вещах, как "Живое время объекта/ссылки".
Ответ 4
Существует экспериментальная функция Firefox и Chrome window.requestIdleCallback(), которая вызывает браузер в режиме ожидания. Это может быть использовано для имитации деструктора экземпляра класса.
Почти такой же эффект можно получить из следующего кода:
setTimeout(function()
{
// Simulate destructor here
},0);
Это устанавливает автоматически отклоненное время ожидания, которое завершается, когда завершается текущий скрипт JavaScript.