0

有没有办法自省 dom 节点以查看是否附加了事件处理程序,这样您就可以有效地编写一个安全的函数来清除 dom 节点,而不必担心事件处理程序留下的内存泄漏?我希望以一种通用的方式做到这一点。

4

2 回答 2

0

据我所知,这可能是不可能的,这是 Mozilla 网站的引述:

https://developer.mozilla.org/en/DOM/element.addEventListener#Memory_issues

内存问题

document.addEventListener("load", function(event) { obj.func(event); }, false);

每次向匿名函数调用 addEventListener 都会创建一个新的侦听器。对匿名函数调用 removeEventListener 无效。匿名函数每次被调用时都会创建一个唯一的对象,它不是对现有对象的引用,尽管它可能会调用一个对象。以这种方式添加事件侦听器时,请确保它只添加一次,它是永久性的(无法删除),直到它被添加到的对象被销毁。

如果听众不是匿名的,你可以这样做。这是来自 YUI 库事件的一段代码:

        /**
         * Returns all listeners attached to the given element via addListener.
         * Optionally, you can specify a specific type of event to return.
         * @method getListeners
         * @param el {HTMLElement|string} the element or element id to inspect 
         * @param sType {string} optional type of listener to return. If
         * left out, all listeners will be returned
         * @return {Object} the listener. Contains the following fields:
         *   type:   (string)   the type of event
         *   fn:     (function) the callback supplied to addListener
         *   obj:    (object)   the custom object supplied to addListener
         *   adjust: (boolean|object)  whether or not to adjust the default context
         *   scope: (boolean)  the derived context based on the adjust parameter
         *   index:  (int)      its position in the Event util listener cache
         * @static
         */           
        getListeners: function(el, sType) {
            var results=[], searchLists;
            if (!sType) {
                searchLists = [listeners, unloadListeners];
            } else if (sType === "unload") {
                searchLists = [unloadListeners];
            } else {
                sType = this._getType(sType);
                searchLists = [listeners];
            }

            var oEl = (YAHOO.lang.isString(el)) ? this.getEl(el) : el;

            for (var j=0;j<searchLists.length; j=j+1) {
                var searchList = searchLists[j];
                if (searchList) {
                    for (var i=0,len=searchList.length; i<len ; ++i) {
                        var l = searchList[i];
                        if ( l  && l[this.EL] === oEl && 
                                (!sType || sType === l[this.TYPE]) ) {
                            results.push({
                                type:   l[this.TYPE],
                                fn:     l[this.FN],
                                obj:    l[this.OBJ],
                                adjust: l[this.OVERRIDE],
                                scope:  l[this.ADJ_SCOPE],
                                index:  i
                            });
                        }
                    }
                }
            }

            return (results.length) ? results : null;
        },

你可以在这里阅读更多:http: //developer.yahoo.com/yui/event/

于 2010-11-02T19:34:47.707 回答
0

这取决于。el.onclick = ...可以有效地删除由属性分配的简单事件处理程序 like ,但attachEvent()IE中没有添加的处理程序列表。在其他浏览器中,内存泄漏并不是什么大问题。

/**
* The purge function takes a reference to a DOM element as an argument. 
* It loops through the element's attributes. If it finds any functions, 
* it nulls them out. This breaks the cycle, allowing memory to be reclaimed. 
* It will also look at all of the element's descendent elements, and clear 
* out all of their cycles as well.
*  - http://javascript.crockford.com/memory/leak.html
*/
function purge(d) {
    var a = d.attributes, i, l, n;
    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            n = a[i].name;
            if (typeof d[n] === 'function') {
                d[n] = null;
            }
        }
    }
    a = d.childNodes;
    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            purge(d.childNodes[i]);
        }
    }
}

如果您想处理这两种情况并管理页面中的所有事件处理程序,您可以将功能包装addEvent在您自己的函数中,并在要删除元素时删除它们。

于 2010-11-02T19:35:32.663 回答