Virkefeltsregler / miljø i js. Overskrivning af onchange-funktion
Hej,
jeg har nogle problemer med at få kaldt en funktion i min superklasse med det rigtige miljø. Først en generel beskrivelse af problemet: jeg har en klasse (eller hvad det nu hedder i js) Obj1 som indeholder et array observers samt en funktion notify(), som benytter observers. Desuden har jeg et nedarvet objekt Obj2 som indeholder en reference select til en select box. Når select ændrer sig (onchange) vil jeg bl.a. gerne kalde notify(), således at det er notify() hørende til det objekt der har referencen select, der kaldes. Jeg har i øjeblikket:
<html> <head> <script> function Obj1(){ var self = this; self.observers = new Array();
this.notify = function(){ //Should do something to all elements in observers //but just print message for now alert("observers has " + self.observers.length + " elements."); }
}
function Obj2(_select){ var select = _select;
select.onchange = function(){alert("Noget andet kode"); this.notify();}; //select.onchange = this.notify; }
Obj2.prototype = new Obj1; Obj2.prototype.constructor = Obj1;
Når jeg vælger noget nyt i theSelect går det galt ved kaldet this.notify(); Jeg får en fejl der siger at objektet ikke understøtter metoden. Er det fordi this i stedet for at referere til master, kommer til at referere til theSelect (i strid med hvad jeg ønsker)? Hvis jeg ændrer tildelingen til select.onchange = this.notify; virker tingene som de skal - jeg får kaldt notify() korrekt og den skriver korrekt at observers har to elementer. Men det er ikke helt godt nok, jeg vil gerne kunne udføre noget kode før kaldet til notify(). På forhånd mange tak.
Noget tyder på, du er vandt til mere 'snavsede' sprog, som VBScript :) Til en start bør du angive dit scriptsprog i dit scripttag. Dernæst bør du undgå at give variabler reserverede ord (eller ord, som har en specifik betydning i JavaScript) som navne ... 'self' og 'select' bør du nok ikke anvende. Ligeledes bør du nok afslutte dine options. Det er ikke påkrævet, men hvis du ønsker din kode skal være fremtidssikret, bør du afslutte dem. Åbne tags har ikke ret lang tid igen.
Så til dit aktuelle problem: Du er inde på det rigtige. 'this' i en callback-funktion refererer ikke til JS-objektet, men til HTML-elementet. Prøv denne kode, så kan du sikkert se forskellen:
<script type="text/JavaScript"> function Obj1() { var oMe = this; oMe.observers = new Array();
this.attach = function(n) { oMe.observers.push(n); }; this.className = "noget"; this.notify = function() { //Should do something to all elements in observers //but just print message for now alert("observers has " + oMe.observers.length + " elements."); } } function Obj2(_select) { var oMe = this; var mySelect = _select; mySelect.onchange = function(){alert("Antal options i din select: "+this.options.length); alert("Noget andet kode"); oMe.notify();}; //select.onchange = this.notify; } Obj2.prototype = new Obj1; Obj2.prototype.constructor = Obj1; </script>
Variablen 'oMe' refererer til selve JS-objektet ... du var faktisk selv inde på det med: 'var self = this;' i din første constructor :)
Nej, problemet er ikke, at jeg er vant til VBScript - problemet er at jeg slet ikke er vant til scriptsprog, så alt der her med løs typning og underlige scope-regler og få fejlmeddelelser forvirrer mig en del ;-) Tak for rådene - de gjorde mirakler for min kode :-) Jeg var ikke klar over at self og select var reserverede ord. Jeg tillader mig lige at stille et tillægsspørgsmål: Hvorfor bruger du this.foo = function(){//} når du laver funktioner, men oMe.bar = 3.14; når du tildeler til variable? Er det fordi this virker fint i constructoren, men ikke i de indlejrede funktioner? Igen, mange tak for hjælpen.
Oooops .... 'oMe.observers = new Array();' er en fejl! Det skal være 'this' og ikke 'oMe'. At det ikke betyder noget, da 'oMe' er sat til at referere til constructor'en, friholder mig ikke - logikken mangler :)
Som du har opdaget, refererer 'this' ikke til objektet, hvis det bruges i en event-handler eller callback-funktion. Her opretter man derimod en variabel, som i oprettelses-øjeblikket peger på objektet. Den vil så også pege på objektet, når event'en udløses. Prøv, om dette eksempel kan hjælpe til en tydeliggørelse:
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.