Re: javascript custom object event handling and this
From: Richard Cornford (Richard_at_litotes.demon.co.uk)
Date: 10/10/04
- Previous message: Dave: "Re: Where am I"
- In reply to: Chris Barber: "Re: javascript custom object event handling and this"
- Next in thread: Jonathan: "Re: javascript custom object event handling and this"
- Reply: Jonathan: "Re: javascript custom object event handling and this"
- Reply: Chris Barber: "Re: javascript custom object event handling and this"
- Messages sorted by: [ date ] [ thread ]
Date: Sun, 10 Oct 2004 16:55:09 +0100
Chris Barber wrote:
> The method you are using to assign the event handler actually
> creates a copy of the event handler function and thus the
> this keyword is now referring to the object that called the
> event handler.
That isn't true. The initial act of assigning a reference to a function
object (resulting from the evaluation of a function expression) to a
property of the object's prototype is the only point at which a new
function object is created. The later act of assigning the value of
the - HandleKeyDown - property of an object instance to the event
handling property of the document does exactly, and only, that. i.e.:
The value of instance's - HandleKeyDown - is a reference to a function
object and it is that reference that is assigned to the event handling
property of the document, both properties then refer to the same (and
only) function object.
The value associated with the - this - keyword when that function object
is executed is determined by how the function is called. If it is called
as a method of an object (any object) then - this - refers to that
object. If it were not called as a method of an object (but directly
executed) then - this - would refer to the global object.
All javascript functions are function objects and exhibit the same
behaviour with regard to the - this - keyword regardless of how and
where they were created.
The problem is that once the reference to the function object has been
assigned to the even handling property of the document, when the event
handler is executed it is called as a method of the document and -
this - is thus a reference to the document.
> You can do this:
>
> <begin code>
>
> //object
> function MyObj()
> {
> this.Prop = "MyObj.Prop";
> }
>
> MyObj.prototype.HandleKeyDown = function()
> {
> // if left arrow key is pressed, alert MyObj.Prop
> if (event.keyCode == 37) alert(this.Prop);
> }
>
> var o = new MyObj();
>
> window.document.onkeydown =
> New Function("return o.HandleKeyDown();")
<snip>
That unambiguously is creating a new function object. And it assumes
that - o - is a stable global variable to which a reference to an
instance of the right type of object has been assigned. It also places
the code that creates the global reference, and assigns the event
handler, outside of the object.
That isn't a problem for a small-ish page specific script, and this
looks like a smallish page specific script because attempting to use an
instance method of the - MyObject - object as the onkeydown event
handler suggests that no more than one instance of - MyObject - will
ever be used (as there is only one - document.onkeydown - handler
available).
In a more general implementation, with the intention of creating more OO
code that was easily re-usable, it is common to need to be in a position
to call an object instance method (often with an event handler) without
any regard for the actions of code that is external to the object. Thus
the object needs to be able to refer to its own instance in a way that
is anonymous (or apparently anonymous to external code). Usually with
the code that does the assigning of the event handler moved inboard (and
a reference to the object to which the handler is to be attached passed
in as a parameter to the constructor or a method call).
A number of techniques (and variations) can be used to associate an
object instance with an event handler anonymously of external code. One
of the simplest is for the constructor to independently arrange a global
reference to its object instances and store sufficient information in
each object for it to be able to resolve a reference to itself
globally:-
Record the current length of the globally accessible array of instances
as the - this.index - property of the constructed object (so that this
object instance can look itself up in the array) and assign a reference
to the constructed object to the array element at that index:-
function MyObj(){
/* Record the current length of the globally accessible array
of instances as the - this.index - property of the
constructed object (so that this object instance can look
itself up in the array) and assign a reference to the
constructed object to the array element at that index:-
*/
MyObj.instances[(this.index = MyObj.instances.lenght)] = this;
this.Prop = "MyObj.Prop";
}
/* Create an array that can store individual object
instance references:-
*/
MyObj.instances = [];
MyObj.prototype.HandleKeyDown = function(e){
e = e||window.event;
// if left arrow key is pressed, alert MyObj.Prop
if (e.keyCode == 37) alert(this.Prop);
}
This approach lends itself to the use of the Function constructor to
create the actual event handler, and to objects that want to use
document.write to insert HTML source that refers back to the individual
object instance. For example:-
MyObj.prototype.attachDocKeyHandler = function(doc){
/* Create a new event handling function that calls an instance
method of this object without any regard for how external
code is using this object instance.
*/
doc.onkeydown = new Function(
'e',
('MyObj.instances['+this.index+'].HandleKeyDown(e)')
);
}
- or:-
MyObj.prototype.writeInputField = function(){
/* Write an input field that has a onkeydown handler that calls
a method of this object instance.
*/
document.write(
('<input type="text" value="" onkeydonw="'+
'MyObj.instances['+this.index+'].HandleKeyDown(event)'+
'">')
);
}
Most other techniques for associating object instances with event
handlers are closure-based, but they tend to be truly anonymous, and
lend themselves to circumstances where constructing string references
would be inconvenient (such as when creating DOM elements) and direct
object and function references more useful. Closures are big subject and
allow many variations on specific techniques. A specific example, and an
explanation of closures can be found at:-
<URL: http://jibbering.com/faq/faq_notes/closures.html >
Richard.
- Previous message: Dave: "Re: Where am I"
- In reply to: Chris Barber: "Re: javascript custom object event handling and this"
- Next in thread: Jonathan: "Re: javascript custom object event handling and this"
- Reply: Jonathan: "Re: javascript custom object event handling and this"
- Reply: Chris Barber: "Re: javascript custom object event handling and this"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|