Reputation: 5843
I have a simple constructor that has firstname and lastname.
function Parent(){
this.firstName;
this.lastName;
}
There are four functions defined in the prototype of that constructor which does it's own tasks.
Parent.prototype.flipName = function () {
return this.lastName + ' ' + this.firstName;
}
Parent.prototype.setFirstName = function (name) {
this.firstName = name;
}
Parent.prototype.setLastName = function (last) {
this.lastName = last;
}
Parent.prototype.getFullName = function (callback) {
// used alert for the sake of simplicity
alert("Callback: " + callback());
return this.firstName + ' ' + this.lastName;
}
To demonstrate this I have attached jsfiddle as well.
So my question is whenever I pass callback on getFullName function this
somehow loses the context to the Parent object (johny in our case) and returns as undefined undefined
. this
however, works fine on getFullName
function.
I am aware that this
is pointing to the window
object instead of the Parent
in the callback but I can't seem to find the reason behind it.
Upvotes: 2
Views: 1296
Reputation: 411
Not enough reputation to add a comment, so here is another answer. Travis has it right for how the question is asked. I think, however, that perhaps the actual use case is possibly a bit more complex. If you use
callback.call(this);
Your callback function is going to be executed with the value of "this" referencing the object that called getFullName. This may or may not be what you want "this" to refer to when you are inside your callback function. So take the following example.
function Parent() {
var self = this;
self.firstName;
self.lastName;
}
function Child() {
var self = this;
self.firstName;
}
Child.prototype.getName = function() {
return this.firstName;
}
Parent.prototype.getFullName = function (callback) {
// used alert for the sake of simplicity
alert("Callback: " + callback.call(this));
return this.firstName + ' ' + this.lastName;
}
Parent.prototype.flipName = function () {
return this.lastName + ' ' + this.firstName;
}
Parent.prototype.setFirstName = function (name) {
this.firstName = name;
}
Parent.prototype.setLastName = function (last) {
this.lastName = last;
}
var johny = new Parent();
johny.setFirstName("Johny");
johny.setLastName("Bravo");
var sue = new Parent();
sue.setFirstName("Sue");
sue.setLastName("Bravo");
// used alert for the sake of simplicity
alert("FullName: " + johny.getFullName(sue.flipName));
When you execute callback.call(this); you are actually going to get "Bravo Johny" when you are probably expecting "Bravo Sue".
I don't know if this is best practice or not, but what I would do instead would be:
alert("FullName: " + johny.getFullName(function() {
return sue.flipName();
}));
Upvotes: 0
Reputation: 147513
In global code, this always references the global object. In function code, the value of this is set by how the function is called (e.g. direct call, as a method, using new, call, apply or bind).
If you want this within the callback to have a certain value, then set it in the call using either call or apply, e.g.
callback.apply(this, args);
If the value of this is not set, it will default to the global object (window in a browser) or in strict mode it will be undefined.
Upvotes: 0
Reputation: 82337
The reason is that when you pass in the function pointer johny.flipName
it is an anonymous function. You can see this by logging it to the console. As a result, the function will execute, but under the global (window
) scope.
To get around this, you must (if you wish) preserve the scope of the callback. You can do this by using call
MDN
Parent.prototype.getFullName = function (callback) {
// used alert for the sake of simplicity
alert("Callback: " + callback.call(this));
return this.firstName + ' ' + this.lastName;
};
Upvotes: 1