避免内存泄漏/使用 Javascript [英] Avoid Memory Leak / Usage Javascript

查看:24
本文介绍了避免内存泄漏/使用 Javascript的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 jQuery 的新手.我有点困惑是好还是可能导致内存泄漏?

I am newbie to jQuery. I am bit confused whether is it fine or may cause memory leak ?

代码如下:在特定日期过滤器上为每个新值调用此方法

Here is the code: This method is called on certain date filters for each new values

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);
  }
}

推荐答案

虽然在编写大型纯 JavaScript 项目时需要避免特定于浏览器的问题,但在使用 jQuery 等库时,应该假设该库的设计帮助您避免这些问题.但是,考虑到内存泄漏很难追踪,并且特定浏览器的每个不同版本的行为都可能不同 - 了解通常如何避免内存泄漏比具体了解要好得多:

Whilst there are browser specific issues that need to be avoided when writing large pure JavaScript projects, when using a library such as jQuery it should be assumed that the library's design helps you avoid these problems. However, considering memory leaks are rather hard to track down, and each different version of a particular browser could behave differently - it is far better to know how to generally avoid memory leaks than being specific:

  1. 如果您的代码被多次迭代,请确保您使用的变量可以被垃圾收集丢弃,并且不会被闭包引用所束缚.
  2. 如果您的代码要处理大型数据结构,请确保您有办法删除或取消数据.
  3. 如果您的代码构建了许多对象、函数和事件侦听器 - 最好也包含一些解构代码.
  4. 尽量避免将 javascript 对象或函数作为属性直接附加到元素 - 即 element.onclick = function(){}.
  5. 如有疑问,请在完成代码后进行整理.
  1. If your code is being iterated many times, make sure the variables you are using can be discarded by garbage collection, and are not tied up in closure references.
  2. If your code is dealing with large data structures, make sure you have a way of removing or nullifying the data.
  3. If your code constructs many objects, functions and event listeners - it is always best to include some deconstructive code too.
  4. Try to avoid attaching javascript objects or functions to elements directly as an attribute - i.e. element.onclick = function(){}.
  5. If in doubt, always tidy up when your code is finished.

您似乎相信调用函数的方式会对泄漏产生影响,但是这些函数的内容总是更有可能导致问题.

You seem to believe that it is the way of calling a function that will have an effect on leaking, however it is always much more likely to be the content of those functions that could cause a problem.

  1. 每当使用事件侦听器时,都会尝试找到一种方法来重用函数,而不是为每个元素创建一个.这可以通过使用事件委托 来实现(捕获祖先/父级上的事件并将反应委托给 event.target),或者编写一个单一的通用函数来以相对方式处理您的元素,最常见的是相对于 this$(this).

当需要创建许多事件处理程序时,通常最好将这些事件侦听器存储为命名函数,以便在完成后再次删除它们.这意味着避免像您这样做时使用匿名函数.但是,如果您知道只有您的代码处理 DOM,您可以回退到使用 $(elements).unbind('click') 删除所有点击处理程序 (匿名或not) 使用 jQuery 应用到所选元素.但是,如果您确实使用后一种方法,那么使用 jQuery 的事件命名空间功能肯定会更好 - 这样您就知道您只是删除了您的事件.即 $(elements).unbind('click.my_app');.这显然意味着您必须使用 $(elements).bind('click.my_app', function(){...});

When needing to create many event handlers, it is usually best to store those event listeners as named functions so you can remove them again when you are finished. This would mean avoiding using anonymous functions as you are doing. However, if you know that it is only your code dealing with the DOM, you can fallback to using $(elements).unbind('click') to remove all click handlers (anonymous or not) applied using jQuery to the selected elements. If you do use this latter method however, it is definitely better to use jQuery's event namespacing ability - so that you know you are only removing your events. i.e. $(elements).unbind('click.my_app');. This obviously means you do have to bind the events using $(elements).bind('click.my_app', function(){...});

更具体:

自动调用匿名函数

being more specific:

auto calling an anonymous 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 添加匿名事件监听器:

adding an anonymous event listener with 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.
  */
});

拆解与解构

关于我的解释,我已经专注于何时不再需要页面并且用户正在离开.然而,在当今充满ajaxed 内容和高度动态界面的世界中,上述内容变得更加重要;不断创建和破坏元素的 GUI.

tearDowns and deconstruction

I've focused - with regard to my explanations - on when the page is no longer required and the user is navigating away. However the above becomes even more relevant in today's world of ajaxed content and highly dynamic interfaces; GUIs that are constantly creating and trashing elements.

如果你正在创建一个动态的 javascript 应用程序,我不能强调拥有带有 .tearDown.deconstruct 方法的构造函数是多么重要,这些方法在代码执行时被执行不再需要.这些应该逐步完成大型自定义对象构造并取消其内容,以及删除已动态创建且不再使用的事件侦听器和元素.在替换元素的内容之前,您还应该使用 jQuery 的 empty 方法 - 这可以用他们的话更好地解释:

If you are creating a dynamic javascript app, I cannot stress how important it is to have constructors with .tearDown or .deconstruct methods that are executed when the code is no longer required. These should step through large custom object constructs and nullify their content, as well as removing event listeners and elements that have been dynamically created and are no longer of use. You should also use jQuery's empty method before replacing an element's content - this can be better explained in their words:

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

为了避免内存泄漏,jQuery 在删除元素本身之前从子元素中删除了其他构造,例如数据和事件处理程序.

To avoid memory leaks, jQuery removes other constructs such as data and event handlers from the child elements before removing the elements themselves.

如果您想删除元素而不破坏其数据或事件处理程序(以便以后可以重新添加),请改用 .detach().

If you want to remove elements without destroying their data or event handlers (so they can be re-added later), use .detach() instead.

使用tearDown 方法进行编码不仅迫使您更整洁地(即确保将相关代码、事件和元素的命名空间放在一起),这通常意味着您以更模块化时尚;这显然更适合您的应用的未来验证、可读性以及可能在以后接管您的项目的任何其他人.

Not only does coding with tearDown methods force you to do so more tidily (i.e. making sure you to keep related code, events and elements namespaced together), it generally means you build code in a more modular fashion; which is obviously far better for future-proofing your app, for read-ability, and for anyone else who may take over your project at a later date.

这篇关于避免内存泄漏/使用 Javascript的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆