jer*_*jer 7 javascript memory-leaks
我有这个代码,我在为项目构建的一些JavaScript组件上使用了这个代码.现在我想知道以下代码是否存在内存泄漏.
哪种选择最合适,A或B还是有更好的方法?
var component = function(){
var self = this; //A - not sure there's a leak here
this.foo = function(){
//var self = this; //B. I can do this but I want to use self in other method as well
var dom = getElementById('someid');
dom.onclick = function(){
self.foo2(); // here I used the self reference
//i cannot use this here, because it refer to dom
}
}
this.foo2 = function(){
var dom = getElementById('someid');
dom.onclick = function(){
self.foo2(); //here I used the self reference
//i cannot use this here, because it refer to dom
}
}
};
// some usage
var c1 = new component();
c1.foo();
Run Code Online (Sandbox Code Playgroud)
T.J*_*der 16
这种方法的问题在于,所有方法的所有代码都将被复制到每个实例中,这可能会变成一个大的内存消耗(除非你不能依赖的执行上下文之间的漂亮优化).你所做的优点是点击处理程序直接调用你想要它调用的方法.
通常的做法是让实例在实例之间共享,将它们放在原型上,并让实例在一个包含良好的闭包上下文中构建小包装函数(例如,一个不关闭无关数据的实例) - 通常由辅助函数创建的原因 - 设置对实例的调用.这样,每个实例只复制少量代码,其中大部分都是共享的.成本是每次点击需要调用一个函数,然后转向并调用另一个函数,但坦率地说,开销并不是一个问题,除非在非常紧的循环中(点击处理程序不是),而内存消耗真的可以在今天的webapps中成为一个问题.
在原型上设置函数在其他地方得到了很好的覆盖,并且通常通过帮助程序来处理,这使得您比原始JavaScript更清晰,更简洁.有关包含良好的闭包上下文中的包装器构建器的示例,请查看Function#bindPrototype中的实现(或其他几个JavaScript库中的类似函数,如MooTools,Closure库等)
基础知识看起来像这样,但我实际上不会这样做:
var component = function() {
this.boundFoo = bind(this, foo); // Remove this if you never use it as a handler
this.boundFoo2 = bind(this, foo2);
};
component.prototype.foo = function() {
var dom = getElementById('someid');
dom.onclick = this.boundFoo2;
};
// (Isn't this exactly what foo did?)
component.prototype.foo2 = function() {
var dom = getElementById('someid');
dom.onclick = this.boundFoo2;
};
function bind(context, func) {
return function() {
func.apply(context, arguments);
};
}
Run Code Online (Sandbox Code Playgroud)
注意如何bind接受上下文和函数,并返回一个新函数,该函数将使用该上下文调用给定函数.
您也可以在分配它们的位置绑定函数,而不是将它们设置为实例上的属性,但是如果您要重用它们(如上图所示),那么保留副本可以实现这一点.
上面有一些问题(所有函数都是匿名的,这意味着你的工具无法帮助你)但是没有进入对象辅助函数,这就是基本的想法.
"Crescent Fresh"指出我最初没有解决内存泄漏问题.要解决的一个重要方面是,对于某些浏览器(主要是IE和衍生产品),在完成它时(例如,离开页面时)解开事件处理程序非常重要.因此,onclick如果您稍后不清除它们,那么您的两个分配都可能是某些浏览器的内存泄漏.这是因为所涉及的浏览器不会处理清除DOM元素和JavaScript对象之间的循环引用(如果它们都没有被引用)(例如,它们相互引用但没有其他任何引用它们).您必须断开DOM元素和JavaScript函数之间的链接,以确保清除它们.如果你使用他们的方法来附加事件处理程序,那么像Prototype这样的Libary会在你卸载页面时为你做这件事.我不知道其他的libs是否足以评论他们是否这样做.
有点OT,但是:
onclick元素的属性(称为"DOM0"风格的设置事件处理程序),而是考虑使用较新的(90年代后期)机制来执行此操作:addEventListener在符合标准的浏览器和attachEventIE上.以这种方式执行操作的一个重大改进是可以在同一元素上为同一事件设置多个处理程序,而使用DOM0处理程序时,如果存在一个,则分配新的处理程序.| 归档时间: |
|
| 查看次数: |
7231 次 |
| 最近记录: |