Jump to content
php.lv forumi

OO JavaScript un eventi


black

Recommended Posts

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 by black
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 :)

Link to comment
Share on other sites

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 by black
Link to comment
Share on other sites

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 by black
Link to comment
Share on other sites

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 by john.brown
Link to comment
Share on other sites

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"

Link to comment
Share on other sites

×
×
  • Create New...