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对象或函数作为属性直接附加到元素 – 即element.onclick = function(){}.
>如果有疑问,您的代码完成后总是整理.
你似乎认为这是调用一个会影响泄漏的功能的方法,但是它总是更有可能成为可能导致问题的那些功能的内容.
有了你的代码,我唯一的建议是:
>每当使用事件侦听器尝试找到重用函数的方法,而不是为每个元素创建一个函数.这可以通过使用event delegation(捕获祖先/父项上的事件并将反应委托给event.target)来实现,或者编码一个单一的通用函数,以相对方式处理元素,最常见的是相对于这个或$(这个).
>当需要创建许多事件处理程序时,通常最好将这些事件侦听器存储为命名函数,以便在完成后再次删除它们.这将意味着避免使用匿名函数.但是,如果您知道只有您的代码处理DOM,则可以使用$(elements).unbind(‘click’)来删除所有使用jQuery应用于所选元素的点击处理程序(匿名).如果您使用后一种方法,那么使用jQuery的事件命名空间能力肯定会更好 – 这样你才知道你只是删除你的事件.即$(元素).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. */ });
撕裂和解构
关于我的解释,我已经专注于何时不再需要该页面,并且用户正在导航.然而,在当今世界的内容和高度动态的界面上,这些变得更加相关;不断创建和删除元素的GUI.
如果您正在创建一个动态的JavaScript应用程序,我不能强调在不再需要代码时执行的.tearDown或.deconstruct方法的构造函数是多么重要.这些应该逐步通过大型自定义对象构造并使其内容无效,以及删除动态创建并且不再使用的事件侦听器和元素.在替换元素的内容之前,您还应该使用jQuery的空方法 – 这可以用他们的话更好地解释:
To avoid memory leaks,jQuery removes other constructs such as data and event handlers from the child elements before removing the elements themselves.
If you want to remove elements without destroying their data or event handlers (so they can be re-added later),use .detach() instead.
不仅使用tearDown方法进行编码会使您更加干练(即确保将相关代码,事件和元素命名为一起保留),这通常意味着您以更模块化的方式构建代码;这对于未来的应用程序,阅读能力以及可能在以后接管您的项目的任何其他人来说显然更好.