Events and "this" caveats

J

Jeremy

Is there any good reading about pitfalls of scoping when using events?

Here is my specific issue:

function MyType()
{
this.foo = "bar";
this.textbox = document.createElement("input");
this.textbox.type = "text";
this.textbox.addEventListener("blur", this.doThings, false);
someElement.appendChild(this.textbox);
}

MyType.prototype.doThings = function()
{
//Wanted "bar", but 'this' is not the MyType object.
//Rather, it's the element that triggered the event.
alert(this.foo);
}

I'm trying to have an event trigger a function call in an object
instance. Is this fundamentally impossible / undesirable in javascript?

Thanks,
Jeremy
 
R

RobG

Is there any good reading about pitfalls of scoping when using events?

The fundamental thing to remember about a function's this keyword is
that it is set by the calling function when the function is called.
To find articles, search on "javascript this keyword" or in these
archives for "this keyword operator". Mike Winter wrote a couple of
great posts a while back.

Here are a few references - some are better than others, you should
get the idea:

Mike Winter 1 (last post):
<URL:
http://groups.google.com.au/group/c...ord+mike+winter&rnum=1&hl=en#28e16b48661bf7e2
Mike Winter 2:
<URL:
http://groups.google.com.au/group/c...ord+mike+winter&rnum=5&hl=en#62dfb987df455e19
Quirksmode:

Here is my specific issue:

function MyType()
{
this.foo = "bar";
this.textbox = document.createElement("input");
this.textbox.type = "text";
this.textbox.addEventListener("blur", this.doThings, false);

Your problem here is that when the event is called, the function's
this keyword is set to the DOM element, not to your object. You can
use call or apply to set the this keyword, or pass a reference to the
object as a parameter.

However you do it, you will probably have a closure involving a DOM
object, which will likey create a memory leak in IE. The following
article tells you how to deal with that;

someElement.appendChild(this.textbox);

}

MyType.prototype.doThings = function()
{
//Wanted "bar", but 'this' is not the MyType object.
//Rather, it's the element that triggered the event.
alert(this.foo);

}

I'm trying to have an event trigger a function call in an object
instance. Is this fundamentally impossible / undesirable in javascript?

Neither, as long as you are careful about memory usage - keep the
contstructor function small and neat and (for IE's sake) detach event
listeners onunload. Here is a very quick and dirty example, Richard
Cornford's article on closures will fill in the blanks:

<div id="div0"></div>

<script type="text/javascript">

function Foo (name, el) {
this.name = name;
this.button = document.createElement('button');

// Create a local variable for convenience
var button = this.button;

// Get a reference to the new object to use later
var obj = this;

button.onclick = function(){

// Use call to set the value of 'this'
// *when the function is called*
obj.showName.call(obj);
}

button.appendChild(
document.createTextNode('show name ' + this.name)
);
el.appendChild(button);
}

Foo.prototype.showName = function(){
alert( this.name );
}

// Create a couple of objects
var x = new Foo('Fred', document.getElementById('div0'));
var y = new Foo('Nerk', document.getElementById('div0'));

</script>
 
J

Jeremy

RobG said:
The fundamental thing to remember about a function's this keyword is
that it is set by the calling function when the function is called.
To find articles, search on "javascript this keyword" or in these
archives for "this keyword operator". Mike Winter wrote a couple of
great posts a while back.

Here are a few references - some are better than others, you should
get the idea:

<snip>

Rob,

That was probably the single most informative post I have ever seen on
c.l.javascript. Thanks!

Before I saw your post, I just adjusted my event handlers to deal with
the expected element instead, and then set a reference in that element's
DOM object to the object I wanted to access. Now, since I don't really
give a crap about IE (note how I'm using w3 event model and ignoring
IE's), I'm going to go back and change it to work the way I originally
wanted.

I only wish usenet wasn't so transient, because I'm sure that post would
be useful to countless people in the future (YOU try searching for
"this" on google groups and see if you get any useful results ;-))

Jeremy
 
R

RobG

function Foo (name, el) {
this.name = name;
this.button = document.createElement('button');

// Create a local variable for convenience
var button = this.button;

// Get a reference to the new object to use later
var obj = this;

button.onclick = function(){

// Use call to set the value of 'this'
// *when the function is called*
obj.showName.call(obj);

Of course call isn't needed here at all, showName is called as a
method of obj so its this keyword will be set to obj:

obj.showName();

will do.
 
R

RobG

Now, since I don't really
give a crap about IE (note how I'm using w3 event model and ignoring
IE's)

If you are developing for the web, that view is difficult to support.
If you are developing for an intranet where something other than IE is
the standard browser, you can probably get away with it.
 
J

Jeremy

RobG said:
If you are developing for the web, that view is difficult to support.
If you are developing for an intranet where something other than IE is
the standard browser, you can probably get away with it.

The second is true. Rather, this is an app mostly for use by
developers, and will never really be seen by any end-users. I'm making
the assumption that developers are well-informed enough not to use I.E.
for daily browsing. I could be wrong, of course, but it is not worth it
to me to code to IE for this particular app.

Jeremy
 

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
473,781
Messages
2,569,619
Members
45,314
Latest member
HugoKeogh

Latest Threads

Top