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

最佳答案

尽管在编写大型纯JavaScript项目时需要避免特定于浏览器的问题,但是在使用诸如jQuery之类的库时,应假定该库的设计有助于您避免这些问题。但是,考虑到内存泄漏相当难以追踪,并且特定浏览器的每个不同版本的行为都可能不同-更好地知道如何避免内存泄漏总比说得好:

  • 如果您的代码被多次迭代,请确保所使用的变量可以被垃圾回收丢弃,并且不与闭包引用 bundle 在一起。
  • 如果您的代码正在处理大型数据结构,请确保您有一种删除或使数据无效的方法。
  • 如果您的代码构造了许多对象,函数和事件侦听器-始终最好也包含一些解构性代码。
  • 尝试避免将javascript对象或函数直接作为属性-element.onclick = function(){}附加到元素。
  • 如果有疑问,请在代码完成后始终整理一下。

  • 您似乎相信这是调用函数的方法,它将对泄漏产生影响,但是,总是更有可能是那些可能引起问题的函数的内容。

    通过上面的代码,我唯一的建议是:
  • 每当使用事件侦听器时,都试图找到一种方法来重用函数,而不是为每个元素创建一个函数。这可以通过使用event delegation(在祖先/父项上捕获事件并将响应委派给event.target)或编码单个通用函数来以相对方式处理您的元素(通常相对于this$(this))来实现。
  • 当需要创建许多事件处理程序时,通常最好将这些事件侦听器存储为命名函数,以便在完成后可以再次将其删除。这将意味着避免在执行操作时使用匿名函数。但是,如果您只知道处理DOM的代码,则可以回退到使用$(elements).unbind('click')删除使用jQuery应用于所选元素的所有单击处理程序(无论是否匿名)。但是,如果确实使用后一种方法,则使用jQuery的事件命名空间功能绝对更好-这样您就知道只删除事件。即$(elements).unbind('click.my_app');。显然,这意味着您必须使用$(elements).bind('click.my_app', function(){...});
  • 绑定(bind)事件

    更具体:

    自动调用匿名函数
    (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.
      */
    });
    

    拆解和解构

    关于我的解释,我着重于不再需要该页面以及用户正在浏览时。但是,在当今内容充斥和高度动态的界面世界中,以上内容变得尤为重要。不断创建和破坏元素的GUI。

    如果要创建动态Javascript应用程序,我无法强调在不再需要代码时执行具有.tearDown.deconstruct方法的构造函数的重要性。这些应逐步遍历大型自定义对象构造并使其内容无效,并删除事件侦听器和已动态创建且不再使用的元素。您还应该在替换元素的内容之前使用jQuery的empty方法-这可以用他们的话更好地解释:

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



    使用tearDown方法进行编码不仅会迫使您做得更整齐(即确保将相关的代码,事件和元素的命名空间保持在一起),而且通常还意味着您以模块化的方式构建代码;对于将来使您的应用程序过时,可读性以及以后可能接管您的项目的其他人来说,这显然要好得多。

    09-20 20:32