附加事件处理程序的元数据存储在哪里?在"DOM",对象,还是......?

Jan*_*ray 8 javascript jquery event-handling javascript-events backbone.js

我一直想知道......所以你有这样的代码:

$('#click-me');
Run Code Online (Sandbox Code Playgroud)

并附上以下内容:

$('#click-me').click(someFunction);
Run Code Online (Sandbox Code Playgroud)

"元数据"在哪里说:

"嘿"jQuery-object#click-me,"当你点击它时我会指向'someFunction'!"

我知道事件处理程序可能会被破坏,例如我的Backbone.js情况,因为我重新渲染整个页面,我的事件停止了触发,一路上破坏了一些背景函数/对象/视图.. (这是上下文至于为什么我问这个问题)

现在,我的问题是:

事件的"元数据"存储在哪里以及它们如何被销毁? 它们是否存储在将其绑定到函数的函数中?它们是否属于DOM'元数据'(如果有的话)本身?

我正在努力学习JavaScript的复杂性,因为我已经厌倦了bug.除此之外,我想知道是否应该留意可能会分离我的事件等的垃圾收集.来自C#,我会说DOM的JavaScript真的是......

(另外,作为附注,我如何访问这些事件并'调试'它们?firefox?chrome?)


UPDATE

用不同的词来说,将DOM元素连接到存储的某个事件的信息在哪里?DOM?对象?(或者...... jQuery是否映射它?JavaScript是否有'元数据'? 它围绕着这个上下文...

gid*_*eon 5

更新:所以我误解了这个问题,你想知道事件是如何绑定在javascript和html的上下文中的.我在下面的原始答案描述了jquery如何创建和管理事件.它归结为对element.addEventListener的调用.

从MDN文档中,您可以看到eventtarget可以是元素,文档,窗口XMLHttpRequest.根据DOM事件w3规范,事件目标添加,删除和分派事件.因此,即使信息也可能存储在封装元素之类的内容中,这将在浏览器级别实现.

从你提到的关于复制然后从正文中替换html的问题中删除事件,我认为浏览器只是给你标记(没有事件元数据),然后当你替换它时,元数据就消失了.(http://jsfiddle.net/qu9bF/1/)


原始答案:jquery事件处理程序如何工作.

好的,所以我开始挖掘这个,用于JQuery 1.4.2(因为我必须使用几个工具,所有这些都没有更新)

首先看看这个:http: //james.padolsey.com/jquery/#v=1.4.2&fn=click

function (fn) {
    return fn ? this.bind(name, fn) : this.trigger(name);
}
Run Code Online (Sandbox Code Playgroud)

这就是定义 click的方式,它实际上并没有在代码中定义.JQuery为所有事件/处理函数定义了这个函数,如下所示,是的!它们是动态创建/定义的:

jQuery.each( ("blur focus focusin focusout load resize scroll unload click
            dblclick " +
        "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
        "change select submit keydown keypress keyup error").split(" "), 
    function( i, name ) {
        // the magic happens here..
        //each string is added as a function to the prototype
        jQuery.fn[ name ] = function( fn ) {
                return fn ? this.bind( name, fn ) : this.trigger( name );
        };//if a handler is NOT specified then attach an event OR call/trigger it

        if ( jQuery.attrFn ) {
                jQuery.attrFn[ name ] = true;
        }
});
Run Code Online (Sandbox Code Playgroud)

从这里,我们需要看看绑定,现在bind()one()也这样定义.在这里搜索"代码:绑定和一个事件"

从这里我用这个小提琴http://jsfiddle.net/qu9bF/使用chrome 来进入代码.块来自于c.each(["bind"如何定义绑定函数.源是缩小的,但chrome可以格式化它.

在此输入图像描述

从这里开始代码调用JQuery.events.add,您可以在这里的Events部分下找到它.这是不是add()有书面文件,我认为

接下来,这段代码就是神奇的.因此它调用element.addEventListenerattachEvent.看看它是如何添加attachEvent.

// Check for a special event handler
// Only use addEventListener/attachEvent if the special
// events handler returns false
if ( !special.setup || 
      special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
      // Bind the global event handler to the element
       if ( elem.addEventListener ) {
             elem.addEventListener( type, eventHandle, false );

        } else if ( elem.attachEvent ) {
             elem.attachEvent( "on" + type, eventHandle );
        }
 }
Run Code Online (Sandbox Code Playgroud)

你有它!:)我希望它能回答你的两个问题.您可以链接到jquery源的非缩小版本并逐步执行以解决问题.IMO有时IE9的调试器更直观(这是我唯一使用的),并使用我提到的页面来浏览源代码.


Tom*_* Tu 2

jQuery 将所有事件绑定和数据缓存存储在 jQuery.cache 对象上。html当您使用 jQuery 、empty、等时,所有用 jQuery 包装并绑定了事件或数据集的 DOM 节点将被自动清除removereplace

这就是为什么永远不要使用 DOMinnerHTML或其他本机 DOM 方法来插入/替换之前由 jQuery 更改的内容非常重要的原因。除非您手动重置 jQuery.cache 对象,否则它将导致无法清理的泄漏。

还有一个未公开的方法jQuery.cleanData,它将 DOM 节点集合作为参数,迭代它们并清理它们的所有事件绑定、数据并从缓存中删除对这些元素的引用。如果您有与主 DOM 树分离的 DOM 片段,并且存在无法正确清理它们的风险,则此选项可能会很有用。