1

I'm new to Javascript. This code mostly works but something weird happens. When I call .send() it fires off the async request and returns normally but the problem is the this context when calling the WebCall.prototype.__stateChangedCallback method. In Chrome this is the XMLHttpRequest object while I'd have thought that it would be the WebCall object instead. Can anyone explain to me why this is?

function log (message) {
    if(typeof console == "object") {
        console.log(message);
    }
}

function WebCall () {
    var __callMethod;
    this.__callMethod = this.createXmlHttpRequest();
}

WebCall.prototype.createXmlHttpRequest = function () {
    if(window.XMLHttpRequest) {
        return new XMLHttpRequest();
    } else {
        return new ActiveXObject("Microsoft.XMLHTTP");
    }
}

WebCall.prototype.beginGet = function(url) {
    this.__callMethod.open("GET", url, true);
    this.__callMethod.onreadystatechange = this.__stateChangedCallback;
    this.__callMethod.send();
}

WebCall.prototype.__stateChangedCallback = function(readyState, status) {
    // this points to the XMLHttpRequest rather than the WebCall object WHY??!
    var request = this.__callMethod;
    if(request.readyState == 4) {
        if (request.status == 200) {
            this.onRequestCompleted(request);
        } else {
            this.onRequestFailed(status, request);
        }
    }
}

WebCall.prototype.onRequestCompleted = function (request) {

}

WebCall.prototype.onRequestFailed = function(status, request) {
    log("Request failed status= " + status);
}
3
  • possible duplicate of Scoping problem with Javascript callback Commented May 20, 2012 at 5:47
  • The problem is on this line: this.__callMethod.onreadystatechange = this.__stateChangedCallback; I'll let them who can better explain why do so. Commented May 20, 2012 at 5:54
  • I figured that much I don't understand why it works like that. What's going on behind the scenes? Commented May 20, 2012 at 5:56

1 Answer 1

1

What you have in WebCall.prototype.__stateChangedCallback is just reference to anonymous function:

WebCall.prototype.__stateChangedCallback = function(readyState, status) {
   //......................................^^^^ anonymous function
}

This line:

this.__callMethod.onreadystatechange = this.__stateChangedCallback;

means , that you have another reference to that same anonymous function. This anonymous function is not part of your prototype object.You just have reference on it in your prototype object.

Workaround would be this:

var that = this;
this.__callMethod.onreadystatechange = function(readyState, status){
    //Calling anonymous function with 'this' context
    WebCall.prototype.__stateChangedCallback.apply( that, arguments );
}
Sign up to request clarification or add additional context in comments.

2 Comments

That's what I ended up doing to fix it. That's really confusing coming from C# thinking it was equivalent to anonymous functions.
@JeremyEdwards The search term you'll want to use for future reading is 'javascript closure'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.