简体   繁体   中英

jQuery code causing memory leak

The following code is causing a memory leak (you can see this happening the more you hover in and out the slower it gets). Unfortunately I am unable to download a javascript profiler in my office (I can, it will just take me a few days/ weeks).

Here is the code, just some simple transitions for a dropdown menu:

$(document).ready(function(){
    breadcrumbOver = function () {
        $(this).stop().animate({ backgroundColor: "#3393b5", textIndent: 15 }, 250);
    }
    breadcrumbOut = function () {
        $(this).stop().animate({ backgroundColor: "#738793", textIndent: 0 }, 250);
    }
    $("nav ul li").hover(
      function () {
        $(this).children('ul.child').stop().slideDown('fast').children('li').hover(breadcrumbOver, breadcrumbOut);
      }, 
      function () {
        $(this).children('ul.child').stop().slideUp('fast').unbind(breadcrumbOver, breadcrumbOut);
      }
    );
});

Can anyone see where a memory leak may be occuring?

Edit: Live example here - http://rcnhca.org.uk/sandbox/ (Repeatedly roll over "Health, Safety and Security" then roll over it's children to see the effect happen, also the animation slideDown doesn't fire sometimes if you roll in and out fast enough).

The problem looks like it might be in your initial selector. It targets all li tags under a ul under nav , which includes all children and grandchildren.

$("nav ul li") ...

This causes it to add a hover callback to all li tags under nav , then when you hover it adds yet another hover callback.

You might want to be more specific with it, such as specifically targeting the direct children.

$("nav>ul>li")

If you have children classes, you can also use :not(.child) to target everything that's not a child. Use console.log (which is built into Chrome or using Firebug) to log what those selectors are pulling to make sure you're getting what you expect.

I see what you're talking about George; the effect is most noticeable when swiping between elements rapidly after the box has been opened several times.

Perhaps this will be something that impacts what you're seeing. I read up on stop() and felt like it could have an impact on what you're seeing. The first attribute you could specify in stop() is clearQueue. The second is equally interesting. Here is what the documentation says about it:

clearQueue A boolean indicating whether to remove queued animation as well. Defaults to false. jumpToEnd A Boolean indicating whether to complete the current animation immediately. Defaults to false.

Might be worth a shot to pass in true like this:

$(this).children('ul.child').stop(true, true)...
// (or  you want the animation to unwind, I suppose)
$(this).children('ul.child').stop(true)...

Also, I checked out unbind as well and I don't think you can pass in two events like you are. Perhaps you could use it this way and not experience the problems you are:

...unbind(breadcrumbOver).unbind(breadcrumbOut);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM