【问题标题】:jQuery - when binding event to multiple elements at once, new instance for each element?jQuery - 一次将事件绑定到多个元素时,每个元素的新实例?
【发布时间】:2011-10-05 20:23:24
【问题描述】:

我的页面中有 100 个按钮(每个按钮都有 class='btn')。

我还有一个单个 按钮,它准备所有其他 100个按钮。

<input type='button' onclick='bindTheClickevent()' />

按下时, - 他调用 bindTheClickevent () - (将点击事件绑定到所有其他 100 个事件)。

在脚本部分我放了:

function bindTheClickevent ()
{
        $(".btn").bind('click',function () {
          $(this).css('color','red');
         });
}

问题

1) 在内存中,anonymous function中有多少instancescreated

2)在内存中,bindTheClickevent() 函数是否会一直be free (GC)? - 请注意 Bind 是在 inside bindTheClickevent 函数中调用...

3) 何时,最终 - bindTheClickevent 函数 will be free to GC ?

让我们做出改变

function bindTheClickevent ()
    {
            $(".btn").bind('click',function () {
              changeColor($(this));
             });
    }

function changeColor(obj)
{
 $(obj).css('color','red');
}

现在 - 改变之后

1)如果我这样做有什么不同吗?

2) 在内存中,anonymous function中有多少instancescreated

3) bindTheClickevent() 函数是否会 be free (GC) ? - 请注意,Bind 是在 inside bindTheClickevent 函数中调用的...

【问题讨论】:

  • ???你在做什么?拥有一个仅绑定 另一个 事件处理程序的 DOM 0 事件处理程序没有多大意义……这只是某种浏览器行为研究主题吗?
  • @Pointy,嗨。我只是给出了一个简单的情况(不是在现实生活中),我想学习这种行为。
  • 在您的第二个示例中,您调用changeColor($(this));,也就是说,您正在传递一个jQuery 对象。在changeColor 中,您再次将其包装在一个jQuery 对象中:$(obj)。这是不必要的

标签: javascript jquery javascript-events event-handling


【解决方案1】:

"1) 在内存中,创建了多少匿名函数的实例?"

哪个匿名函数?

对于内联 onclick,您会得到一个分配给元素的 onclick 属性的函数,如下所示:

function(event) {

    bindTheClickevent();

}

... 或类似的,具体取决于实现。当元素被取消引用或函数从onclick 属性中取消引用时,该函数将免费用于 GC。

关于jQuery代码:

$(".btn").bind('click',function () {
    $(this).css('color','red');
});

...虽然匿名函数是共享的,但您看不到的是,如果相关元素尚未绑定 jQuery 处理程序,则 jQuery 将在内部为每个元素。

该内部处理程序是实际上绑定到元素的,当元素接收到事件时,将调用该处理程序,分析事件,并调用您最初传递的处理程序(如有必要) .

这意味着 100 个 jQuery 绑定元素等于 101 个唯一函数实例

为了确保使用 jQuery 绑定的任何处理程序都经过 GC,您需要确保始终使用 jQuery 删除 DOM 元素。否则,存储在 jQuery.cache 中的所有数据(包括处理程序)都不会被清理,因此它们将始终通过全局 jQuery 命名空间进行引用。


编辑:

鉴于有 100 元素具有类 btn,它们没有任何由 jQuery 绑定的处理程序,那么这段代码:

$(".btn").bind('click',function () {
    $(this).css('color','red');
});

...将创建 101 唯一的 Function 实例。

为什么是101

嗯,jQuery 所做的是第一次将处理程序绑定到元素时,它会在内部为每个元素创建一个 unique 通用处理程序。这是事件发生时实际调用的处理程序,处理所有事件类型。

您的处理函数从未实际绑定到元素。

因此,通用内部处理程序在调用时将分析发生的事件,并查看是否有任何处理程序已使用与该事件类型匹配的.bind() 与给定元素相关联。如果是这样,它会调用通过的处理程序。

现在假设你绑定了另一个处理程序:

$(".btn").bind('mouseenter',function () {
    $(this).css('color','blue');
});

...因为我们绑定到 same 元素,它们已经有必要的 internal handler 并且不需要创建另一个。因此,所发生的一切就是您传递的函数在内部被引用,并在需要时由通用内部处理程序调用。

因此,鉴于上面的代码 sn-ps,现在存在 102 唯一的 Function 实例。

【讨论】:

  • 为什么有额外的匿名函数?我明确告诉他去声明的函数“bindTheClickevent”
  • 匿名函数如何共享?如果“bindTheClickEvent”返回那个匿名函数,不是每个调用都返回一个单独的实例吗?
  • @RoyiNamir:如果你说的是内联onclick,那就是它的工作原理。您的字符串"bindTheClickevent();" 得到eval'd,并包装在一个匿名函数中。
  • @Pointy:我认为这个问题对于绑定在哪里有些混淆。我假设只有一个内联onclick,而.btn 选择是完全独立的。那是共享的那个。 (我还假设内联只调用一次。)
  • @Ӫ_._Ӫ ,你说得对。只有 1 个按钮(局外人)通过调用一次 bindTheClickevent() 来“激活”其他 100 个按钮
【解决方案2】:

看起来在这两种情况下只创建了一个函数实例。似乎对匿名函数的引用作为每个元素的事件处理程序附加。

Example - 使用闭包来显示按钮事件处理程序之间的范围共享。

请注意,如果您涉及闭包,这可能会导致有趣的行为,因为所有元素将共享相同的函数(和闭包范围)。

不,您声明的函数不会因为它们的全局作用域而被 GC'd。

另外

要独立附加它们(而不是通过引用),请使用 .each() 循环选择元素并单独附加函数。

Example

$('.btn').each(function() {
    $(this).bind('click',function() {
        // each '.btn' has it's own copy of
        // this anonymous function
    }
});

【讨论】:

  • 我不相信这是真的。 “bindTheClickEvent”的每次调用必然会为事件处理程序创建一个新的 Function 实例。 (现在,在内部,JavaScript 引擎可能能够在它们之间共享实际代码,但仍然会有不同的 Function 实例。)
  • @Pointy 只有一个调用bindTheClickEvent()
  • @jondavidjohn 是的,但是在其中创建了 100 个其他匿名函数(不同的)...?
  • 这就是我要告诉你的,看看我上面的 jsfiddle 示例,看起来好像所有事件处理程序作为一个组附加时,共享函数范围并且每个元素都获得对事件的引用处理函数...
  • 不知道如何解释我上面的例子。
【解决方案3】:

如果你这样做:

for (someiterations)
{
    $(myobj).bind("click",function()
    {
        // ...bla...
    });
}

在这种情况下,您每次迭代都会创建一个新函数。 在您的函数中,这不会发生,因为您将函数传递给参数,所以 有一个地方存储了它的引用(是的,函数参数)会做这样的事情:

for (iterations)
{
    myob.addEventHandler(event, funcref);
}

现在应该没问题了:

  1. 不这么认为,但是不确定语法。
  2. 1 如我所述
  3. 不,因为它在全局范围内并且没有分配给实例,您可以将其视为常量,而不是变量

注意:匿名函数不会被释放,它被事件处理器引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-22
    • 1970-01-01
    相关资源
    最近更新 更多