Автоматическое удаление обработчика событий при очистке дочерних узлов dom - PullRequest
0 голосов
/ 02 ноября 2010

Есть ли способ проанализировать dom-узел, чтобы увидеть, подключены ли обработчики событий, чтобы вы могли эффективно написать безопасную функцию для очистки dom-узлов, не беспокоясь об утечках памяти, оставленных обработчиками событий? Я надеялся сделать это в общем виде.

Ответы [ 2 ]

0 голосов
/ 02 ноября 2010

Это зависит. Простые обработчики событий, назначенные свойством, таким как el.onclick = ..., могут быть эффективно удалены, но в IE нет списка обработчиков, добавленных через attachEvent(). Утечки памяти не слишком важны в других браузерах.

/**
* 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 функциональность в своей собственной функции и удалить их, когда элемент должен быть удален. *

0 голосов
/ 02 ноября 2010

Из того, что я вижу, это может быть невозможно, вот цитата с сайта Mozilla:

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

Проблемы с памятью

document.addEventListener ( "нагрузка", функция (событие) {obj.func (событие); }, ложь);

Вызов addEventListener для анонимная функция создает новый слушатель каждый раз. призвание удалитьEventListener для анонимного функция не имеет никакого эффекта. Аноним Функция создает уникальный объект каждый время называется, это не хотя ссылка на существующий объект это может назвать один. При добавлении события слушатель таким образом, убедитесь, что это добавляется только один раз, он является постоянным (может не удаляться) пока объект был добавлен в уничтожен.

если слушатель не является анонимным, вы можете сделать это. Вот фрагмент кода из библиотеки YUI Event:

        /**
         * 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:
         * &nbsp;&nbsp;type:   (string)   the type of event
         * &nbsp;&nbsp;fn:     (function) the callback supplied to addListener
         * &nbsp;&nbsp;obj:    (object)   the custom object supplied to addListener
         * &nbsp;&nbsp;adjust: (boolean|object)  whether or not to adjust the default context
         * &nbsp;&nbsp;scope: (boolean)  the derived context based on the adjust parameter
         * &nbsp;&nbsp;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/

...