Conectando eventos com singletons dinâmicos

Em alguns aplicativos da web, é possível ter objetos singleton que são instanciados uma vez, mas inicializados com frequência. Por exemplo (suponha jQuery):

(function(window){
window
.MyNamespace = window.MyNamespace || {};
var MySingleton = MyNamespace.MySingleton = {
init
: function() {
//init code
}
}
MySingleton.init(); //init on load
})(window);

O código acima adiciona um singleton ao seu namespace global (que pode ser referenciado por MyNamespace.MySingletonoutro lugar em seu código). Muitas vezes, na init()função, ocorre a associação de eventos:

init: function() {
this.elem = $('#myelem');

//wire events to this specific element
this.elem
.on('click', '.myclass1', this.handleClick)
.on('change', '.myclass2', this.handleChange)
//etc
;

//wire events to doc, like triggered custom events
$
(document)
.on('customevent', this.handleCustomEvent)
//etc
;
}

Isso é bom se o elemento principal de seus objetos permanecer no DOM e seu singleton não for initrefeito. Mas e se você tiver um webapp que carregue dinamicamente o seu HTML, substituindo o que estava lá antes? Seus elementos DOM serão religados com sucesso (supondo que você tenha novos elementos DOM), mas seus documenteventos serão religados, o que significa que eles reagirão um número crescente de vezes conforme os usuários folhearem seu aplicativo.

Lidar com isso é simples: crie uma hasBoundpropriedade em seu singleton (exemplo simplificado):

var MySingleton = {
hasBound
: false
, init: function() {
// [ DOM wireup ]

if (!this.hasBound) {
// [ document wireup ]
this.hasBound = true;
}
}
}

Agora você pode reconfigurar initseu singleton com segurança, sem se preocupar com a multi-ligação de seus eventos!