Подтвердить что ты не робот

Избегайте утечки памяти/использования Javascript

Я новичок в jQuery. Я немного смущен, хорошо ли это или может вызвать утечку памяти?

Вот код: этот метод вызывается для определенных фильтров даты для каждого нового значения

function preapreTooltip(chart) {
    var tickLength = chart.xAxis[0].tickPositions.length,
        ticks = chart.xAxis[0].ticks,
        tickPositions = chart.xAxis[0].tickPositions;
    for ( var iCntr = 0; iCntr < tickLength; iCntr++) {
         var tickVal = tickPositions[iCntr];

    //.label or .mark or both
    (function(tickVal) { // Is this good practice to call function like this?
        ticks[tickVal].label
        .on('mouseover', function(event) { // Is this good practice to call function like this?
            var label = '', labelCnt=0;
            $(chart.series).each(function(nCntr, series) {
                //business logic for each series
            });

           // calling method to show values in a popup
        });

        ticks[tickVal].label.on('mouseout', function(event) { // Is this good practice to call function like this?
            try {
                hideWrapper(); // hides popup
            } catch (e) {
            // do nothing
            }
        });

    })(tickVal);
  }
}
4b9b3361

Ответ 1

Несмотря на то, что при написании больших проектов с открытым кодом JavaScript необходимо избегать особых проблем с браузером, при использовании библиотеки, такой как jQuery, следует предположить, что дизайн библиотеки помогает избежать этих проблем. Однако, учитывая утечку памяти, довольно сложно отследить, и каждая другая версия конкретного браузера может вести себя по-другому - гораздо лучше знать, как вообще избежать утечек памяти, чем быть конкретным:

  • Если ваш код повторяется много раз, убедитесь, что переменные, которые вы используете, могут быть отброшены сборкой мусора и не привязаны к ссылкам закрытия.
  • Если ваш код имеет дело с большими структурами данных, убедитесь, что у вас есть способ удаления или аннулирования данных.
  • Если ваш код создает много объектов, функций и прослушивателей событий, всегда лучше включать и некоторые деконструктивные коды.
  • Старайтесь избегать прикрепления объектов или функций javascript к элементам непосредственно в качестве атрибута - т.е. element.onclick = function(){}.
  • Если вы сомневаетесь, всегда убирайте код, когда ваш код завершен.

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

С вашим кодом выше, мои единственные предложения:

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

  • При необходимости создания многих обработчиков событий обычно лучше хранить эти прослушиватели событий как именованные функции, чтобы вы могли удалить их снова, когда закончите. Это означало бы избежать использования анонимных функций, как вы это делаете. Однако, если вы знаете, что это только ваш код, связанный с DOM, вы можете отказаться от использования $(elements).unbind('click'), чтобы удалить все обработчики кликов (анонимные или нет), применяемые с помощью jQuery для выбранных элементов. Однако, если вы используете этот последний метод, определенно лучше использовать способность jQuery event namespacing - чтобы вы знали, что вы удаляете только свои события. т.е. $(elements).unbind('click.my_app');. Это, очевидно, означает, что вам нужно привязывать события, используя $(elements).bind('click.my_app', function(){...});

более конкретно:

автоматический вызов анонимной функции

(function(){
  /*
   running an anonymous function this way will never cause a memory
   leak because memory leaks (at least the ones we have control over) 
   require a variable reference getting caught in memory with the 
   JavaScript runtime still believing that the variable is in use, 
   when it isn't - meaning that it never gets garbage collected. 
   This construction has nothing to reference it, and so will be 
   forgotten the second it has been evaluated.
  */
})();

добавление анонимного прослушивателя событий с помощью jQuery:

var really_large_variable = {/*Imagine lots of data here*/};

$(element).click(function(){
  /*
   Whilst I will admit not having investigated to see how jQuery
   handles its event listeners onunload, I doubt if it is auto-
   matically unbinding them. This is because for most code they
   wont cause a problem, especially if only a few are in use. For
   larger projects though it is a good idea to create some beforeunload
   or unload handlers that delete data and unbind any event handling.
   The reason for this is not to protect against the reference of the
   function itself, but to make sure the references the function keeps
   alive are removed. This is all down to how JS scope works, if you
   have never read up on JavaScript scope... I suggest you do so.

   As an example however, this anonymous function has access to the
   `really_large_variable` above - and will prevent any garbage collection
   system from deleting the data contained in `really_large_variable`
   even if this function or any other code never makes use of it. 
   When the page unloads you would hope that the browser would be able
   to know to clear the memory involved, but you can't be 100% certain
   it will *(especially the likes of IE6/7)* - so it is always best
   to either make sure you set the contents of `really_large_variable` to null
   or make sure you remove your references to your closures/event listeners.
  */
});

tearDowns и деконструкция

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

Если вы создаете динамическое приложение javascript, я не могу подчеркнуть, насколько важно иметь конструкторы с методами .tearDown или .deconstruct, которые выполняются, когда код больше не требуется. Они должны проходить через большие конструкции пользовательских объектов и сворачивать их содержимое, а также удалять прослушиватели событий и элементы, которые были динамически созданы и больше не используются. Вы также должны использовать метод jQuery empty перед заменой содержимого элемента - это может быть лучше объяснено в их словах:

http://api.jquery.com/empty/

Чтобы избежать утечек памяти, jQuery удаляет из дочерних элементов другие конструкторы, такие как данные и обработчики событий, перед удалением самих элементов.

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

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

Ответ 2

Вот отличная статья, чтобы обнаружить утечку памяти с помощью Chrome или Safari: http://javascript.crockford.com/memory/leak.html

Используются не известные функции панели инструментов разработчика.

Интересный и очень полезный!

EDIT

Это была не хорошая ссылка (но все же полезна). Вот один из них: http://gent.ilcore.com/2011/08/finding-memory-leaks.html