Pasar de la gestión de eventos clásica a la delegación de eventos en JavaScript OOP

La antigua gestión de eventos en la que cada controlador para acciones específicas se adjuntó directamente al elemento objetivo se está quedando obsoleta, ya que las consideraciones sobre el rendimiento y el ahorro de memoria comenzaron a extenderse en la comunidad de desarrolladores.

Las implementaciones de delegación de eventos tuvieron una aceleración desde que jQuery actualizó la antigua.bind() y.live() métodos con el nuevo.on() Método para permitir la delegación.

Esto determina un cambio en algunos enfoques experimentados, en los que, para utilizar la delegación de eventos, es necesario volver a trabajar. Estoy tratando de desarrollar algunas de las mejores prácticas mientras mantengo el estilo de codificación de mi biblioteca, y busqué situaciones similares que enfrentan otros desarrolladores para encontrar una respuesta.

Al usar OOP con funciones como constructores, normalmente tengo interfaces para la creación de objetos como esta:

var widget = new Widget({
    timeout: 800,
    expander: '.expanders'
});

con literales de objetos dados como argumento, proporcionando un mapa limpio de nombres y valores de la entrada pasada. La clase subyacente a este código podría ser algo como lo siguiente:

var Widget = function(options) {
    // some private members
    var _timeout;
    var _$widget;
    var _$expander;

    // methods
    this.init = function() {
        _timeout = options.timeout || 500;
        _$expander = $(options.expander);
        _$widget = _$expander.next();
        _$expander.on('click', _toggle);
    };
    var _toggle = function(e) {
        if (_$widget.is(':visible')) {
            _$widget.hide(_timeout);
        } else {
            _$widget.show(_timeout);
        }
    };
    this.init();
};

El uso de métodos "privados" me dio algunos beneficios en términos de legibilidad y limpieza del código (solo los métodos útiles están públicamente expuestos al usuario), más allá de la pequeña ganancia en rendimiento (cada resolución de alcance lleva más tiempo que una variable local). Pero cuando se habla de manejadores de eventos, choca con el paradigma de delegación de eventos.

Pensé en hacer públicos los métodos que solía asociar internamente con los oyentes de la clase:

    this.toggle = function(e) {
        if (_$widget.is(':visible')) {
            _$widget.hide(_timeout);
        } else {
            _$widget.show(_timeout);
        }
    };

luego, conduciendo externamente, o en otra clase proxy, la delegación apropiada con algo como esto:

var widget = new Widget({
    expander: '.expanders'
});

$(delegationContext).on('click', '.expanders', widget.toggle);

pero no me pareció el mejor enfoque, al fallar en la exposición de un método no útil en la interfaz, así que intenté una forma para que la clase principal conozca directamente toda la información para delegar el evento de forma autónoma, a través de la interfaz:

var widget = new Widget({
    timeout: 800,
    expander: {
        delegationContext: '.widgetContainer',
        selector: '.expanders'
    }
});

lo que permitiría seguir utilizando métodos privados internamente en la clase:

var $context = $(options.expander.delegationContext);
$context.on('click', options.expander.selector, _toggle);

¿Cuáles son sus prácticas y sugerencias al respecto?
¿Y cuáles son las principales tendencias de otros desarrolladores de los que has oído hablar hasta hoy?

Respuestas a la pregunta(1)

Su respuesta a la pregunta