'this' and prototypes

A

Andrew Poulos

I have some code that's structured a bit like this:

Con = function(choice, el) {
this.choice = choice;
document.getElementById(el).onclick = this.choiceClicked;
}

Con.prototype.choiceClicked = function() {
alert(this.choice);
}

foo = new Con(1,"bar")

Why is it when I click on the element "bar" this choice alerts as
'undefined'? In the prototype 'this' is the element clicked and not what
is was expecting (the object 'foo'). I'd like the 'this' in the
prototype to refer to 'foo': is there some way to do this?

Andrew Poulos
 
C

Christopher Benson-Manica

EventListener said:
Someone else wrote (context restored)

I'm extremely curious as to why this doesn't work as one would intend.
Clearly "this" in the first line refers to the Con object; it
therefore seems that it should have been possible for the ECMA script
designers to differentiate

document.getElementById(el).onclick = this.choiceClicked;

from

document.getElementById(el).onclick = 'this.choiceClicked()';

Is the basic issue that event attributes may only be references to
global functions? Would

var a={};
a.foo=function() {alert('foo');}

document.getElementById( 'bar' ).onclick=a.foo;

work as intended?
 
M

Martin Honnen

Christopher Benson-Manica wrote:

it
therefore seems that it should have been possible for the ECMA script
designers to differentiate

document.getElementById(el).onclick = this.choiceClicked;

from

document.getElementById(el).onclick = 'this.choiceClicked()';

There is certainly a difference between the result of the right hand
side expression in the first assigment and the one in the second assigment.
The first yields a function object, the second a string.
And the function object the first right hand side expression yields is
not bound to the this object, it is simply a function object. The this
object only exists when a function is called.

That is what the ECMAScript specification deals with. Event handlers and
HTML element attributes are not in any way part of that specification or
what its designers dealt with.
 
C

Christopher Benson-Manica

Martin Honnen said:
There is certainly a difference between the result of the right hand
side expression in the first assigment and the one in the second assigment.
The first yields a function object, the second a string.

Well darn it. I was and am aware of the fact that 'this' refers to
the element that generated the event in an event handler, so I really
can't explain how I managed to produce that post. Time to make some
more coffee.
 
M

Michael Winter

On 15/09/2005 14:38, Andrew Poulos wrote:

[snip]
Con = function(choice, el) {
this.choice = choice;
document.getElementById(el).onclick = this.choiceClicked;
}

Con.prototype.choiceClicked = function() {
alert(this.choice);
}

[snip]

This issue has been discussed many, many times in the past. The most
recent I recall is

Subject: .addEventListener() not finding the right object method
Date: 2005/08/26 14:37 GMT
Message ID: (e-mail address removed)


<URL:http://groups.google.co.uk/group/co...read/thread/e8702c77bcd68fc8/45eed8c571173a3e>

where I referenced

Subject: How to understand the javascript class model?
Date: 2005/08/25 02:28 GMT
Message ID: [email protected]


<URL:http://groups.google.co.uk/group/co...read/thread/9b041b9103b6de0f/2065870c97d74b50>

from the day before.

Mike
 
R

Robert

Andrew said:
I have some code that's structured a bit like this:

Con = function(choice, el) {
this.choice = choice;
document.getElementById(el).onclick = this.choiceClicked;
}

Con.prototype.choiceClicked = function() {
alert(this.choice);
}

foo = new Con(1,"bar")

Why is it when I click on the element "bar" this choice alerts as
'undefined'? In the prototype 'this' is the element clicked and not what
is was expecting (the object 'foo'). I'd like the 'this' in the
prototype to refer to 'foo': is there some way to do this?

I learned to use closures to do this.

function Con(choice, e1)
{
this.choice = choice;
document.getElementById(e1).onclick = Con.createClickHandler(this)
}

function _Con_createClickHandler(obj)
{
return function(event)
{
obj.choiceClicked();
}
}

function _Con_choiceClicked()
{
alert(this.choice);
}

Con.prototype.choiceClicked = _Con_choiceClicked;
Con.createClickHandler = _Con_createClickHandler;
 
M

Michael Winter

On 16/09/2005 11:27, Robert wrote:

[snip]
function Con(choice, e1)
{
this.choice = choice;
document.getElementById(e1).onclick = Con.createClickHandler(this)
}

function _Con_createClickHandler(obj)
{
return function(event)
{
obj.choiceClicked();
}
}

Incidentally, this will still create the memory leak that you've harped
on about recently. :p

In the factory function, there is an object reference to a DOM object,
obj. This object will (eventually) have a property that is a reference
to a function object. This function object has, in its scope chain, a
reference to the original DOM object.

This is exactly the same process that you've seen elsewhere. The only
difference is that the assignment is deferred to another execution context.

The discussions I linked to mention workable alternatives, as will
previous threads in this group.
function _Con_choiceClicked()
{
alert(this.choice);
}

Con.prototype.choiceClicked = _Con_choiceClicked;
Con.createClickHandler = _Con_createClickHandler;

Don't create unnecessary intermediary globals. Instead, assign the
function object to the property directly:

Con.prototype.choiceClicked = function() {
alert(this.choice);
};

Mike
 

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

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top