Обнаружение утечек памяти в JavaScript

TagLib Sharp имеет поддержку чтения тегов ID3.

7
задан Peter Mortensen 30 October 2010 в 14:34
поделиться

1 ответ

Потребление памяти

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

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

Настройка функций в прототипе хорошо освещена в другом месте и обычно выполняется с помощью помощников, которые позволяют вам быть более ясным и кратким, чем необработанный JavaScript. Примеры конструкторов оболочек в хорошо ограниченных контекстах замыкания можно найти в реализации Function # bind в Prototype (или аналогичных функциях в любой из нескольких других библиотек JavaScript, таких как MooTools, библиотека Closure и т. Д.)

Основы выглядят так, но я бы не стал делать это так:

var component = function() {
    this.boundFoo = bind(this, foo); // Remove this if you never use it as a handler
    this.boundFoo2 = bind(this, foo2);
};
component.prototype.foo = function() {
    var dom = getElementById('someid');
    dom.onclick = this.boundFoo2;
};
// (Isn't this exactly what foo did?)
component.prototype.foo2 = function() {
    var dom = getElementById('someid');
    dom.onclick = this.boundFoo2;
};
function bind(context, func) {
    return function() {
        func.apply(context, arguments);
    };
}

Обратите внимание на то, как bind принимает контекст и функцию и возвращает новую функцию, которая будет вызывать данную функцию с этим контекстом.

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

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

Память Утечки

"Crescent Fresh" указал Я действительно не обращался к утечкам памяти изначально. Один важный аспект, который необходимо решить, заключается в том, что в некоторых браузерах (в основном IE и производных) важно, чтобы отключил обработчик событий, когда вы закончите с ним (например, когда покидаете страницу). Итак, оба ваших onclick назначения могут быть утечками памяти в некоторых браузерах, если вы не очистите их позже. Это связано с тем, что задействованные браузеры не обрабатывают очистку циклических ссылок между элементами DOM и объектами JavaScript, когда ни один из них еще не упоминается (например, они ссылаются друг на друга, но ничто другое не ссылается на них). Вы должны разорвать связь между элементом DOM и функцией JavaScript, чтобы убедиться, что оба они очищены. Такие библиотеки, как Prototype, делают это за вас, когда страница выгружается, если вы используете их методы для присоединения обработчиков событий; Я не знаю другие библиотеки достаточно хорошо, чтобы прокомментировать, знают ли они.

Другие примечания

В некоторой степени OT, но:

  1. Также изучите концепцию «делегирования событий» - обработчики щелчков - отличное место для использования делегирования, поскольку они всплывают. Вы можете обнаружить, что вам понадобится всего пара обработчиков на уровне контейнера, а не сотни на уровне элемента.
  2. Вместо того, чтобы назначать свойство onclick элемента, которое называется «DOM0» стиль настройки обработчиков событий, рассмотрите возможность использования для этого более новых (конца 90-х) механизмов: addEventListener в браузерах, соответствующих стандартам, и attachEvent в IE. Одним из значительных улучшений этого способа является то, что для одного и того же события в одном элементе можно установить несколько обработчиков, тогда как с обработчиками DOM0 назначение нового уничтожает старый, если он есть.
16
ответ дан 6 December 2019 в 12:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: