0

I'm learning OOP javascript... In my example code, I can't access properties and methods from within the ajax methods ... why, and what would be the right way to do that? http://jsbin.com/votajaxo/1/

var Person = function(name){
    this.name = name;
};

Person.prototype = {
    doAjax: doAjax,
    changeName: changeName
};

function doAjax(url){
    console.log(this.name); // John

    $.ajax({
        url: url,
        beforeSend: function(xhr){
            console.log(this.name); // undefined
            console.log(typeof this.changeName); // undefined
            xhr.abort();
        }
    });
}

function changeName(newName){
    this.name = newName;
}

var p = new Person('John');
p.doAjax('/handler');
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
spikes
  • 25
  • 5
  • See http://stackoverflow.com/questions/4886632/what-does-var-that-this-mean-in-javascript. There are many dups. Also see http://stackoverflow.com/questions/111102/how-do-javascript-closures-work – elclanrs Apr 21 '14 at 03:45

3 Answers3

3

You have to explicitly set the context in which your closure will be called; jQuery provides this functionality via the context: option to $.ajax():

$.ajax({
    url: url,
    context: this, // <-- add this
    beforeSend: function(xhr){
        console.log(this.name);
        console.log(typeof this.changeName);
        xhr.abort();
    }
});
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
2

You will want to use a closure to retain reference to the "this" of the object:

var Person = function(name){
    this.name = name;
};

Person.prototype = {
    doAjax: doAjax,
    changeName: changeName
};

function doAjax(url){
    var context = this;
    console.log(this.name); // John

    $.ajax({
        url: url,
        beforeSend: function(xhr){
            console.log(context.name); // John
            console.log(typeof context.changeName); 
            xhr.abort();
        }
    });
}

function changeName(newName){
    this.name = newName;
}

var p = new Person('John');
p.doAjax('/handler');
Harvey A. Ramer
  • 763
  • 7
  • 13
0

You can also bind your desired context to callback.. so that when it gets executed it gets proper context.

function doAjax(url){
    console.log(this.name); // John

    $.ajax({
        url: url,
        beforeSend: function(xhr){
            console.log(this.name); // undefined
            console.log(typeof this.changeName); // undefined
            xhr.abort();
        }.bind(this) // <-- binds call to current context.
    });
}

http://www.smashingmagazine.com/2014/01/23/understanding-javascript-function-prototype-bind/

Vikram
  • 4,162
  • 8
  • 43
  • 65