Mantieni “questo” riferimento nel gestore di eventi prototipo javascript

Qual è il modo corretto di conservare this riferimento javascript in un gestore di eventi memorizzato all’interno del prototipo dell’object? Mi piacerebbe stare lontano dalla creazione di vars temporanei come ‘_questo‘ o ‘quello’ e non posso usare un framework come jQuery. Ho visto molte persone parlare dell’uso di una funzione “bind”, ma non ero sicuro di come implementarlo nel mio scenario.

 var Example = function(foo,bar){ this.foo = foo; this.bar = bar; }; Example.prototype.SetEvent = function(){ this.bar.onclick = this.ClickEvent; }; Example.prototype.ClickEvent = function(){ console.log(this.foo); // logs undefined because 'this' is really 'this.bar' }; 

Trovo che bind() sia la soluzione più pulita finora:

 this.bar.onclick = this.ClickEvent.bind(this); 

Tra l’ altro this è chiamato per convenzione molto spesso.

Controlla il documento MDN sul bind : https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

Utilizzando questa funzionalità, è ansible modificare l’ambito (che cosa è):

 Example.prototype.SetEvent = function(){ this.bar.onclick = this.ClickEvent.bind(this); }; 

Essere consapevoli, tuttavia, che questa è una nuova aggiunta a EMCA e quindi potrebbe non essere supportata in tutti i programmi utente. È disponibile un pollyfill nel documento MDN collegato sopra.

Il problema con bind è supportato solo da IE9 + .

La funzione può essere polyfilled con es5-shim , ma non è completamente identica all’implementazione nativa:

  • Avvertenza: la funzione associata ha una proprietà prototipo.
  • Avvertenza: le funzioni associate non cercano troppo per impedirti di manipolare i loro arguments e le proprietà del caller .
  • Avvertenza: le funzioni associate non hanno check in call e si apply per evitare l’esecuzione come costruttore.

Un’altra alternativa può essere jQuery.proxy :

 $(elem).on('click', $.proxy(eventHandler, this)); 

Ciò è ancora più utile se si desidera rimuovere il gestore eventi in seguito, poiché quando una funzione passa attraverso il metodo proxy , jQuery genera un nuovo valore guid e quindi applica quel guid sia alla funzione core sia alla funzione proxy risultante, quindi che è ansible utilizzare il riferimento alla funzione originale per separare un callback del gestore di eventi che è stato inoltrato:

 $(elem).off('click', eventHandler); 

Altra soluzione: utilizzare le “funzioni freccia” introdotte da ES6. Quelli hanno la particolarità di non cambiare il contesto, IE ciò che this indica. Ecco un esempio:

 function Foo(){ myeventemitter.addEventListener("mousedown", (()=>{ return (event)=>{this.myinstancefunction(event)}; /* Return the arrow function (with the same this) that pass the event to the Foo prototype handler */ })()); } Foo.prototype.myinstancefunction = function(event){ // Handle event in the context of your Object } 

Specifiche della funzione freccia @ MDN

modificare

Stai attento con esso. Se lo si utilizza sul lato client e non si è certi delle funzionalità dell’interprete JS, si noti che il vecchio browser non riconoscerà le funzioni della freccia ( vedere Statistiche CANI ). Utilizzare questo metodo solo se SAPETE cosa lo eseguirà (solo browser recenti e app NodeJS)