Assigning methods to objects, and assigning onreadystatechange to an XMLHttpRequest -- an inconsiste

W

weston

So, the following apparently works as a method of grafting a method
onto an object (using the squarefree JS shell):

obj = { x: 1, inc: null }
result> [object Object]
obj.inc = function () { this.x++ }
result> function () { this.x++; }
obj.inc()
obj.x
result> 2

And by works, I mean that when I create an object, and then assign one
of its properties an anonymous function, the "this" keyword within said
anyonymous function apparently refers to the object itself. Convenient.
I like it.

The problem is, in the context of an XMLHttpRequest object, this
doesn't seem to work as well for me. Again, using the squarefree js
shell:

xhr = new XMLHttpRequest()
result> [object XMLHttpRequest]
xhr.onreadystatechange = function () { alert(this.responseText); }
result> function () { alert(this.responseText); }
xhr.open("GET","http://www.squarefree.com/shell/shell.html",true)

Now, one might think this would produce an alert containing the
text/html of shell.html. But it doesn't. The value of this.responseText
is apparently undefined.

A slight variation reveals an apparent explanation:

xhr.onreadystatechange = function () { alert(this); }
result> function () { alert(this); }
xhr.open("GET","http://www.squarefree.com/shell/shell.html",true)

This produces an alert that ... displays the code of the anonymous
function itself.

So, apparently, in this case, the "this" keyword refers to the function
itself, and it would seem I can't graft-on methods that have access to
the other properties of the XMLHttpRequest object. At least via the
"this" keyword.

Can someone help me understand what the differences between the two
situations are?

Also... the reason why I'm interested in this largely has to do with
some vague stylistic discomfort. Much of the code I've seen and written
using XMLHttpRequests uses global / lexically scoped variables to get
information across curly-braces between functions. If I could graft
methods onto the request objects themselves, I think I could cut down
on this. I'm open to other suggestions.
 
R

Richard Cornford

weston said:
So, the following apparently works as a method of grafting a method
onto an object (using the squarefree JS shell):

obj = { x: 1, inc: null }
result> [object Object]
obj.inc = function () { this.x++ }
result> function () { this.x++; }
obj.inc()
obj.x
result> 2

And by works, I mean that when I create an object, and then
assign one of its properties an anonymous function, the
"this" keyword within said anyonymous function apparently
refers to the object itself. Convenient. I like it.

As expressed, that effect is an illusion as - this - is determined
always, and only, by how a function is called. If you call one as a
method of an object, as you do above, - this - will refer to that
object.
The problem is, in the context of an XMLHttpRequest object,
this doesn't seem to work as well for me. Again, using the
squarefree js shell:

xhr = new XMLHttpRequest()
result> [object XMLHttpRequest]
xhr.onreadystatechange = function () { alert(this.responseText); }
result> function () { alert(this.responseText); }
xhr.open("GET","http://www.squarefree.com/shell/shell.html",true)

Now, one might think this would produce an alert containing
the text/html of shell.html. But it doesn't. The value of
this.responseText is apparently undefined.

The problem is that you don't know how the onreadystatechange handler is
being called by the browser so you cannot know in advance what - this -
will refer to. Experimentation reveals that (for IE at least) it is not
called as a method or any particular object.
A slight variation reveals an apparent explanation:

xhr.onreadystatechange = function () { alert(this); }
result> function () { alert(this); }
xhr.open("GET","http://www.squarefree.com/shell/shell.html",true)

This produces an alert that ... displays the code of the
anonymous function itself.

I bet that is not universally true.
So, apparently, in this case, the "this" keyword refers
to the function itself, and it would seem I can't
graft-on methods that have access to the other
properties of the XMLHttpRequest object. At least
via the "this" keyword.

Yes, you cannot use - this - practically, so you must provide access to
objects of interest by some other means (and there are plenty of
options).
Can someone help me understand what the differences
between the two situations are?

The difference is between knowing how a function is being called and not
knowing. Generally when you don't know you can work it out by trying,
but if the results are not useful you still have to deal with that.
Also... the reason why I'm interested in this largely
has to do with some vague stylistic discomfort. Much of
the code I've seen and written using XMLHttpRequests
uses global / lexically scoped variables to get information

Globals are not so good, as multiple asynchronous requests will tend to
overwrite them. Exploiting closures (the lexically scoped stuff) is much
better.
across curly-braces between functions.
If I could graft methods onto the request objects
themselves, I think I could cut down on this. I'm
open to other suggestions.

That is quite an 'if' as there is no reason to expect that the request
object can have properties added to it at runtime (except that that is
common in javascript environments) as they are host objects and may not
provide the facility.

Bus since you cannot get - this - to reliably refer to the request
object the question is academic.

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
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top