this thing al开发者_如何学运维most works:
function myClass(url) {
this.source = url;
this.rq = null;
this.someOtherProperty = "hello";
// open connection to the ajax server
this.start = function() {
if (window.XMLHttpRequest) {
this.rq = new XMLHttpRequest();
if (this.rq.overrideMimeType)
this.rq.overrideMimeType("text/xml");
} else
this.rq = new ActiveXObject("Microsoft.XMLHTTP");
try {
this.rq.onreadystatechange = connectionEvent;
this.rq.open("GET", this.source, true);
this.rq.send(null);
this.state = 1;
} catch (err) {
// some error handler here
}
}
function connectionEvent() {
alert("i'm here");
alert("this doesnt work: " + this.someOtherProperty);
}
} // myClass
so it's nothing more than having the XMLHttpRequest object as a member of my class, instead of globally defined, and invoking it in the traditional way. however, inside my connectionEvent callback function, the meaning of "this" is lost, even though the function itself is scoped inside myClass. i also made sure that the object that i instantiate from myClass is kept alive long enough (declared global in the script).
in all the examples of using javascript classes that i saw, "this" was still available inside the inner functions. for me, it is not, even if i take my function outside and make it a myClass.prototype.connectionEvent. what am i doing wrong? thank you.
The reason it's not working is that in Javascript, this
is defined entirely by how a function is called, not where it's defined. This is different than some other languages.
To have this
mean what you expect, you'd have to ensure that explicitly by "binding" it:
this.start = function() {
var self = this; // Set up something that survives into the closure
/* ...lots of stuff omitted... */
this.rq.onreadystatechange = function() {
// Call `connectionEvent`, setting `self` as `this` within the call
connnectionEvent.call(self);
};
There's more information about this
management in this blog post, but basically: When a function is called without any particular effort made to set this
, this
within the function will always be the global object (window
, on browsers). There are two ways to set this
when making a call:
- Using
Function#call
(orFunction#apply
) as I did above, passing in the object reference to use asthis
as the first parameter. That calls the function and setsthis
to whatever you passed in. The difference between#call
and#apply
is how you supply further arguments to pass into the function. With#call
you supply them as further arguments to the#call
call (e.g.func.call(thisArg, arg0, arg1, arg2)
), whereas with#apply
you supply them as an array in the second argument (func.apply(thisArg, [arg0, arg1, arg2])
). - Using dotted notation: If you have an object that has a property with a function assigned to it (like your
start
property), calling it by using the object instance, a dot, and the property name (this.start()
orfoo.start()
, etc.) will call the function and setthis
to the object instance within the call. So the dotted notation does two entirely distinct things: Looks up the property and finds a function as its value, and calls the function such thatthis
is set to the object during the call. Literally it's like:var f = obj.func; f.call(obj)
.
Slightly off-topic, but: Barring a really good reason to, I wouldn't reinvent this wheel. There are lots of libraries out there to simply XHR calls. jQuery, Prototype, Closure, and nearly all the rest.
精彩评论