我需要在 DOM 事件回调中使用闭包吗?
我正在尝试构建一个类似 jQuery.live 的函数。 Helper
是一个具有 _liveEvent
和 _addEventListener
方法的类。 Helper._addEventListener
只是 W3C addEventListener
的跨浏览器版本。
Helper.prototype._liveEvent = function(type, evt, ofunc) {
var elHand = document;
type = type.toUpperCase();
this._addEventListener(elHand, evt, function(me) {
// Inside here I use the `type` variable.
// I don't know why but it works.
for (var el = me.srcElement; el.nodeName !== 'HTML';
el = el.parentNode)
{
if (el.nodeName === type || el.parentNode === null) {
break;
}
}
if (el && el.nodeName === type) {
ofunc.call(el, me);
}
});
};
我使用不同的类型运行 Helper._liveEvent
函数两次,它工作得很好。我认为由于 type
变量是在 _liveEvent
上下文中设置的,因此 _addEventListener
回调只能看到该变量的最后一个版本。但事实并非如此,它似乎工作得很好。
我的问题是:
- 为什么
_addEventListener
回调可以看到该类型的两个版本? - 这是否意味着我的代码正在泄漏内存?
更新
另一个例子让我更好地理解了这一点,但我不确定我是否完全理解它。
function foo(i) {
setTimeout(function() {
console.log(i);
}, 400);
}
// Prints 1, 2, 3
for (var i = 1; i < 4; i++) {
foo(i);
}
function bar() {
for (var i = 1; i < 4; i++) {
setTimeout(function() {
console.log(i);
}, 400);
}
}
// Prints 4, 4, 4
bar();
I'm trying to build a jQuery.live like function.Helper
is a class that has the _liveEvent
and _addEventListener
methods. Helper._addEventListener
is just a CrossBrowser version of W3C addEventListener
.
Helper.prototype._liveEvent = function(type, evt, ofunc) {
var elHand = document;
type = type.toUpperCase();
this._addEventListener(elHand, evt, function(me) {
// Inside here I use the `type` variable.
// I don't know why but it works.
for (var el = me.srcElement; el.nodeName !== 'HTML';
el = el.parentNode)
{
if (el.nodeName === type || el.parentNode === null) {
break;
}
}
if (el && el.nodeName === type) {
ofunc.call(el, me);
}
});
};
I'm running the Helper._liveEvent
function twice with different types, and it works just fine. I thought that since the type
variable was set inside the _liveEvent
context the _addEventListener
callback could see only the last version of that variable. But it's not the case, it seems to be working fine.
My questions are:
- Why the
_addEventListener
callback can see both versions of the type? - Does it mean my code is leaking memory?
UPDATE
This other example made me understand this better, but I'm not sure I understand it fully yet.
function foo(i) {
setTimeout(function() {
console.log(i);
}, 400);
}
// Prints 1, 2, 3
for (var i = 1; i < 4; i++) {
foo(i);
}
function bar() {
for (var i = 1; i < 4; i++) {
setTimeout(function() {
console.log(i);
}, 400);
}
}
// Prints 4, 4, 4
bar();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
_addEventListener()
的匿名函数的每个实例创建了一个单独的闭包作用域,每个实例都有自己的elHand
和type
值>。_addEventListener()
, each having its own values ofelHand
andtype
.实际上,您已经在创建一个闭包。这就是为什么:
有效 - 调用匿名函数创建一个新的闭包,并将
id
设置为i
的当前值。 (我个人喜欢将参数称为与我要使用的变量相同的东西,因此我可以将其视为“锁定”该函数的变量值)。就内存泄漏而言,两次调用不会导致泄漏。如果 GC 按我认为的方式工作,它会删除任何没有指向它们的闭包。特别是,当您离开某个页面时,与该页面关联的所有内存都会被释放。
Effectively, you already are creating a closure. This is why:
works - calling the anonymous function creates a new closure with
id
set to the current value ofi
. (Personally I like to call the argument the same thing as the variable I want to use, so I can think of it as "locking" the value of the variable for that function).As far as memory leaks go, two calls is not going to cause a leak. If GC works the way I think it does, it removes any closures that have no pointers to them. In particular, when you leave a page, any memory associated with that page is freed.