black Posted May 9, 2007 Report Posted May 9, 2007 (edited) Kā zināms, JavaScripts eventus izpilda tā DOM elementa kontekstā, kurš ir eventa avots. Zemāk redzamajā piemērā onClickHandler() funkcijai 'this' atgriezīs nevis 'LoginManager' instanci, bet gan 'input' elementa instanci. Jautājums - kāds ir vislabākais veids, lai eventu handlerī (onClickHandler) varētu izsaukt LoginManager.doSomething() funkciju? <form> <input type="submit" id="buttonId" name="button" value="Send Me!" /> </form> function LoginManager() { this.button=null; this.id = "LoginManager"; } LoginManager.prototype.init = function() { this.button = getById("buttonId"); this.button.onclick = this.onClickHandler; } LoginManager.prototype.onClickHandler = function(event) { alert(this.id); // displays 'buttonId' instead of 'LoginManager' this.doSomething(); // error } LoginManager.prototype.doSomething = function() { alert("done"); } Edited May 9, 2007 by black
v3rb0 Posted May 9, 2007 Report Posted May 9, 2007 a kā pasaki ka nospiežot uz pogas jāizpildas onClickHandler?
black Posted May 9, 2007 Author Report Posted May 9, 2007 skat augstāk. this.button.onclick = this.onClickHandler; Vēl, protams, ir metode, kas izsauc FormManager.init(), un getById(), un vēl 10.000 rindiņas cita koda, bet tas šeit nav svarīgi.
john.brown Posted May 9, 2007 Report Posted May 9, 2007 function LoginManager() { this.button=null; } LoginManager.prototype.init = function() { this.button = document.getElementById("buttonId"); this.button.eventRouter = this; this.button.onclick = this.onClickHandler; } LoginManager.prototype.onClickHandler = function(event) { alert(this.id); this.eventRouter.doSomething(); // error } LoginManager.prototype.doSomething = function() { alert("done"); } Šitā it kā strādā. Vismaz uz FF :)
black Posted May 9, 2007 Author Report Posted May 9, 2007 (edited) Vēl kādam ir kāds variants? Es pats esmu sameklējis vairākus (bet neviens, ieskaitot šo, īsti nepatīk). john.brown piemērs ir 1:1 no AJAX in Action, skat. pie "Attaching a Model to the DOM node" Mīnuss konkrētajam piemēram - "When using this pattern, we create a cyclic reference between a DOM and a non-DOM variable, and web browser folklore has it that this is bad for garbage collection under certain popular browsers of the day." Edited May 9, 2007 by black
john.brown Posted May 9, 2007 Report Posted May 9, 2007 1:1 no AJAX in Action, Nu, no turienes viņš arī ir :) Bet domāju, cita varianta nav. Iekš js ar pareizu instanšu saprašanu ir zināmas problēmas...
v3rb0 Posted May 9, 2007 Report Posted May 9, 2007 un ja eventRouter nesien klāt pie pogas, bet gan pie kāda globāla-statiska js objecta?
black Posted May 9, 2007 Author Report Posted May 9, 2007 (edited) Nu ir jau vēl arī citi varianti, tikai jautājums, vai tie ir labāki. Zemāk skat. variantu ar 'closures', anonīmu funkciju, kas paliek 'karājoties' ārpus metodes pēc tam, kad 'init' ir pabeidzis izpildīties. Gribētos atrast variantu, kuram ir vismazāk trūkumu, lai to tad visur varētu izmantot. function LoginManager() { this.button=null; } LoginManager.prototype.init = function() { this.button = document.getElementById("buttonId"); var self = this; var clickHandler = function() { self.onClickHandler(this); } this.button.onclick = clickHandler; } LoginManager.prototype.onClickHandler = function(event) { alert(this.id); self.doSomething(); } LoginManager.prototype.doSomething = function() { alert("done"); } Edited May 9, 2007 by black
black Posted May 9, 2007 Author Report Posted May 9, 2007 Globālie objekti man kaut kā nepatīk, lai gan arī tas ir viens no risinājumiem.
john.brown Posted May 9, 2007 Report Posted May 9, 2007 (edited) Man jau gan šķiet, ka jebkurā gadījumā risinot šito sanāk cikliska saite. Visa atšķirība ir, ka vienā gadījumā tā ir acīmredzama (kā ar this.button.eventRouter), otrā - nomaskēta, kā funkcijas gadījumā... IMHO, labāk tomēr acīmredzams variants :) P.S. tanī pašā Ajax in Action tak bij arīaprakstīts, kā ar tām cikliskajām saitēm cīnīties. Vesala sadaļa tam bij veltīta :) Edited May 9, 2007 by john.brown
john.brown Posted May 9, 2007 Report Posted May 9, 2007 bubu, a teorētiskā motivācija tādam tavam lēmumam ir? Jeb vienk kods skaistāks liekas? :)
black Posted May 9, 2007 Author Report Posted May 9, 2007 Varam jau piemeklēt arī motivāciju :) http://www.brockman.se/writing/method-references.html.utf8 "This code works as intended, but the solution is inelegant. While it is unlikely that the name eventRouter will ever conflict with anything, you’re still essentially polluting someone else’s namespace. Another problem with this approach is that it theoretically breaks encapsulation, since you are in fact setting up a backdoor to your logic. Anyone with access to the HTML document that your element is attached to could aquire a reference to your backdoored element, and, by extension, your private data. This will probably not present itself as a practical problem to anyone, but it necessarily remains a fundamental inelegancy. Binding a variable to the value of this and then closing over it is a superior approach"
Recommended Posts