'this' is undefined in JavaScript class methods

Carson Myers picture Carson Myers · Oct 25, 2010 · Viewed 98.1k times · Source

I'm new to JavaScript. New as far as all I've really done with it is tweaked existing code and wrote small bits of jQuery.

Now I'm attempting to write a "class" with attributes and methods, but I'm having trouble with the methods. My code:

function Request(destination, stay_open) {
    this.state = "ready";
    this.xhr = null;
    this.destination = destination;
    this.stay_open = stay_open;

    this.open = function(data) {
        this.xhr = $.ajax({
            url: destination,
            success: this.handle_response,
            error: this.handle_failure,
            timeout: 100000000,
            data: data,
            dataType: 'json',
        });
    };

    /* snip... */

}

Request.prototype.start = function() {
    if( this.stay_open == true ) {
        this.open({msg: 'listen'});
    } else {

    }
};
//all console.log's omitted

The problem is, in Request.prototype.start, this is undefined and thus the if statement evaluates to false. What am I doing wrong here?

Answer

Chetan S picture Chetan S · Oct 25, 2010

How are you calling the start function?

This should work (new is the key)

var o = new Request(destination, stay_open);
o.start();

If you directly call it like Request.prototype.start(), this will refer to the global context (window in browsers).

Also, if this is undefined, it results in an error. The if expression does not evaluate to false.

Update: this object is not set based on declaration, but by invocation. What it means is that if you assign the function property to a variable like x = o.start and call x(), this inside start no longer refers to o. This is what happens when you do setTimeout. To make it work, do this instead:

 var o = new Request(...);
 setTimeout(function() { o.start(); }, 1000);