Reputation: 328
You'll have to forgive me -- I'm a seasoned Java programmer, but still struggling with the semantic differences between the languages!
I have a small JavaScript object constructor. It includes a jQuery function which gets a small piece of Ajax data. When the data gets returned, I want to make use of it in conjunction with a variable (renderMode) defined at the top of the object constructor but, presumably because of function block closure, I am getting 'undefined'.
Here's the example:
function AsyncRequest() {
this.renderMode = RenderMode.NONE;
this.setId = setId;
function setId(v) {
this.id = v;
}
this.setURL = setURL;
function setURL(v) {
this.URL = v;
}
this.render = render;
function render(element) {
$.get(
this.URL,
function (data) {
// The data comes back just fine ...
// ... and I know a value was previously assigned to renderMode
// ... in this instance of AsyncRequest, but how do I get at it ?
console.log("Render mode: " + this.renderMode); // this.renderMode is undefined
}
);
}
}
Upvotes: 2
Views: 81
Reputation: 165
You can create a var for "this" in the main function:
function AsyncRequest() {
var self = this;
self.renderMode = RenderMode.NONE;
self.setId = setId;
...
function render(element) {
$.get(
self.URL,
function (data) {
console.log("Render mode: ", self.renderMode);
}
);
}
}
Upvotes: 0
Reputation: 1074138
Unlike in Java, this
in JavaScript is determined primarily by how a function is called, not where it's defined. (ES6 will add a way to have this
lexically-bound, but for now it's primarily bound by the function call.) So the callback you're passing into $.get
is getting called with this
not referring to the object you expect.
You can solve this by using the fact you have a closure:
function render(element) {
var self = this; // <=== Note
$.get(
this.URL,
function (data) {
console.log("Render mode: " + self.renderMode);
// Note ----------------------^
}
);
}
There, we're remembering what this
was when render
was called in a variable called self
(the name doesn't matter), and then using the fact that the callback function is a closure over the context of the call to render
, and so we have access to the self
variable.
You can also solve it with ES5's Function#bind
:
function render(element) {
$.get(
this.URL,
function (data) {
console.log("Render mode: " + this.renderMode); // this.renderMode is undefined
}.bind(this) // <== Note
);
}
Function#bind
returns a function that, when called, calls the original function with this
set to the value you give it.
More (on my blog):
Upvotes: 2