Using object methods in addEventListener

J

Joe Kelsey

When you use addEventListener (or addEvent in IE) to call an object
method, does it call it with the correct this parameter?

The ECMAScript reference has a lot to say about the caller using
Function.prototype.call or Function.prototype.apply and passing the
correct this pointer for the context, but how does addEventListener
determine the correct this pointer. Or does it just punt and pass the
global context, thus making it impossible to refer to the object this
in an object method used as an event listener?

I could not find any reference to this in the W3C DOM-2 documentation.

/Joe
 
L

Lasse Reichstein Nielsen

When you use addEventListener (or addEvent in IE) to call an object
method, does it call it with the correct this parameter?

Absolutely! Ofcourse, whether that "this" value is the one you expect,
that is another question :).

If you use
node.addEventListener("click",foo.method,false)
and then click on the node, the function referred to by "foo.method"
is executed with "this" referring to "node". Just as if you had
used
node.onclick=foo.method;
It never refers to "foo", which some might consider the correct value
of "this".
(Tested in Opera 7 and Mozilla FB 0.6)

If you use the IE version:
node.attachEvent("onclick",foo.method)
then the function is executed with this referring to the global (window)
object.
(Tested in IE6)
The ECMAScript reference has a lot to say about the caller using
Function.prototype.call or Function.prototype.apply and passing the
correct this pointer for the context, but how does addEventListener
determine the correct this pointer.

It takes the object the event handler is assigned to, just as if it
was made a property of that object.
Or does it just punt and pass the global context, thus making it
impossible to refer to the object this in an object method used as
an event listener?

IE does that.
I could not find any reference to this in the W3C DOM-2 documentation.

That would be in W3C DOM 2 Events, and it doesn't say that. The
specification of an eventListener is an interface (i.e., an object
description) that contains a function to be called. That is because
it is written for languages that doesn't have first class functions,
like Javascript does. In such a language, the "this" value would be
the wrapper object for the function.
In Javascript we just pass the function itself, so it doesn't have
an obvious base object. Smart people made addEventHandler works as
close to assigning directly to the "onclick" property, but it is
not a requirement. IE didn't.

The DOM 2 Event specification gives another way of accessing the
node that an eventListener is assigned to: the "currentTarget" property
of the event. That won't help you for IE, ofcourse.

/L
 
J

Joe Kelsey

Lasse Reichstein Nielsen said:
Absolutely! Ofcourse, whether that "this" value is the one you expect,
that is another question :).

If you use
node.addEventListener("click",foo.method,false)
and then click on the node, the function referred to by "foo.method"
is executed with "this" referring to "node". Just as if you had
used
node.onclick=foo.method;
It never refers to "foo", which some might consider the correct value
of "this".
(Tested in Opera 7 and Mozilla FB 0.6)

If you use the IE version:
node.attachEvent("onclick",foo.method)
then the function is executed with this referring to the global (window)
object.
(Tested in IE6)

So attachEvent in IE does something completely different from
specifying code directly in onclick="" in HTML? I mean I can put this
directly into the onclick HTML spec

<input blah...blah...
onclick="updateSomething (param1, 'param2', this.value);">

and expect that this.value refers to the input node. But if I
construct the Function inside javascript

var firstPart = "updateSomething (param1, ";
var lastPart = ", this.value);";
addEvent (node, "change", new Function (firstPart + "'param2'" +
lastPart), false);

Where node is a previously created element (e.g.,
document.createElement) and addEvent is a suitably defined function to
take care of the difference between addEventListener and attachEvent,
then this.value will not work in IE?

If IE really supplies the global window context as this to the event
function, then it seems impossible to emulate the HTML behavior from
javascript.

I want to move some bizarre use of <script> as template html into
javascript. That means creating dynamic elements that include
onchange handlers. All of the handlers basically look the same except
for the 'param2' value.

/Joe
 
R

Richard Cornford

var firstPart = "updateSomething (param1, ";
var lastPart = ", this.value);";
addEvent (node, "change", new Function (firstPart +
"'param2'" + lastPart), false);
<snip>

node.onchange = new Function(firstPart +"'param2'" + lastPart);

Works consistently in current browsers.

If you insist on playing with addEventListener and attachEvent then
closure based solutions can be applied to rectify IE's deficiencies (and
maybe include param2 in the closure and avoid the need to explicitly
call the Function constructor to create a new function for each event
handler).

Richard.
 
J

Joe Kelsey

Richard Cornford said:
node.onchange = new Function(firstPart +"'param2'" + lastPart);

Works consistently in current browsers.

Does a standard exist which specifies this behavior or do the browsers
"just do it"? As far as I can tell from reading the DOM documents, no
"onchange" attribute exists in the various Element or Node
descriptions. Have I missed something?

Also, why prefer a closure using a function expression to creating a
new Function object? Does creating a new Function object involve some
sort of penalty that function expressions do not have? Do you just
prefer closures? Something to do with parse-time versus run-time?

/Joe
 
J

Jim Ley

Does a standard exist which specifies this behavior or do the browsers
"just do it"?

It's HTML DOM 0 as it's known...
As far as I can tell from reading the DOM documents, no
"onchange" attribute exists in the various Element or Node
descriptions.

No, AddEventListener etc. is the appropriate method, but DOM Level 0
is more sensible now (you use "document" right, that's not in a
standard either just DOM 0)
Also, why prefer a closure using a function expression to creating a
new Function object? Does creating a new Function object involve some
sort of penalty that function expressions do not have?

It's very expensive, it's just like eval...

Jim.
 
R

Richard Cornford

Joe Kelsey said:
"Richard Cornford" <[email protected]> wrote in message

Does a standard exist which specifies this behavior or do
the browsers "just do it"?

They just do it, and have been doing it for so long that no browser
manufacturer would dare drop the feature for fear of producing a browser
that looked like it did not work with much of the web.

The number of events supported on different elements in the DOM varies,
with IE supporting the greatest number of events through defined
properties of the elements and Netscape 4 supporting just a limited
number of events (and having fewest accessible elements anyway). Though
Netscape 4 support is not relevant as it has already failed at
document.createElement (or before).
As far as I can tell from reading the DOM documents, no
"onchange" attribute exists in the various Element or Node
descriptions. Have I missed something?

I used the onchange property because you were passing the string
"change" as the second parameter to your - addEvent - function, so I
assumed that you were interested in setting onchange handlers and would
not be attempting to use them on elements that do not support onchange
attributes. I haven't attempted to confirm this but I would suspect
that, for any Element type, the range of event handlers that can be set
as properties of the element corresponds exactly with the range of
events that can trigger functions when addEventListener or attachEvent
are used.
Also, why prefer a closure using a function expression to
creating a new Function object?
Does creating a new Function object involve some
sort of penalty that function expressions do not have?

Why not? They both will fail under their own individual and very limited
set of circumstances. For that reason the Function constructor might be
preferred as its failure can be ascertained by testing before it
happens, allowing more controlled fall-back. While when inner functions
fail it is because the JavaScript version is so old that they are not
supported, becoming syntax errors and killing off script execution for
the entire page, but we are talking JavaScript version 1.0 (and maybe
1.1), so not something that needs to be worried about these days.

Closures are not without there drawbacks, they are among the easiest
ways of creating the circular JavaScript object <-> DOM element
references that induce the memory leak problem in IE. But can usually be
coded to avoid that problem, and if not additional code can be used as a
solution to that problem.

In this case I mentioned closures because they would offer the option of
addressing two conditions at once, the scope resolution of the function
in IE and the problem of passing a different - param2 - to each
function.

The Function constructor carries the penalty that its function body is
parsed on each invocation of the constructor. Authors used to IE will
often be expecting excellent performance from the eval function and the
Function constructor. Unfortunately both experience a wide range of
performances in different implementations, with some implementations
being up to 6 times slower than IE under most circumstances and, with
some code structures, up to 400 times slower (but that is very much the
exception).

Ironically one place where the Function constructor offers manifest
benefits is performance critical code that requires the repeated
execution of the same function (such as sorting a very big array of
objects using a custom comparison function) where the function body will
have to use parameters/identifiers/indexes unknown until the execution
of the script. A closure could do it but the Function constructor could
create a function hard-coded to the task and as a result as efficient as
it could be.
Do you just prefer closures?

I like closures. They allow very interesting possibilities (to say the
least).
Something to do with parse-time versus run-time?

That could be a factor.

In the end each has its place, I just think that the scope for the
appropriate application of the Function constructor is much more limited
than for the appropriate application of closures.

Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,082
Messages
2,570,588
Members
47,209
Latest member
Ingeborg61

Latest Threads

Top