Reputation: 450
I have an object with a number of functions:
var someScopeScopedObject = {
myFunction1: function () {
console.log('foo');
},
myFunction2: function () {
this.myFunction1();
}
init: function (callback) {
callback();
}
}
So if I call someScopeScopedObject.myFunction2
that works fine
But If I do someScopeScopedObject.init(someScopeScopedObject.myFunction2)
then I get an error that this.myFunction1 is undefined
Why is this
not valid when I call into the function that way?
Upvotes: 2
Views: 75
Reputation: 15715
this
refers to the function in which it is declared,
So in your example,
var someScopeScopedObject = {
myFunction1: function () {
console.log('foo');
},
myFunction2: function () {
this.myFunction1();
}
init: function (callback) {
callback();
}
}
myFunction1 is not declared inside myFunction2, so
` myFunction2: function () {
this.myFunction1();
}.
is not possible, because this.myFunction1();
tries to call method myfunction1 which should be declared inside myfunction1
which is not declared there.
Edit:
someScopeScopedObject.myFunction2();
is possible because you are calling the method myFunction1 which is defined inside someScopeScopedObject
someScopeScopedObject.init(someScopeScopedObject.myFunction2);
is not possible because, you pass someScopeScopedObject.myFunction2
as a callback function in this case here to the init function,
init: function (callback) {
callback();
}
It then calls
myFunction2: function () {
this.myFunction1();
}
here you refer this.myFunction1();
--- This doen not exist, since you are refering to myfunction1 defined inside myfunction2, which is not!
Upvotes: 1
Reputation: 2980
When you pass myFunction2
as an argument to something, it loses the reference to the object it belongs to. this
now refers to the function itself, and not someScopeScopedObject
, hence your problem :)
This is also why some libraries take an object context for methods, ie. jasmine's spyOn(someScopeScopedObject, "myFunction2")
, to keep the scoping correct.
An example work-around (like the one used by jasmine) could look like this:
var someScopeScopedObject = {
myFunction1: function () {
console.log('foo');
},
myFunction2: function () {
this.myFunction1();
},
init: function (context, callbackName) {
context[callbackName]();
}
}
This would allow you to do the following:
someScopeScopedObject.init(someScopeScopedObject, "myFunction2");
This is not the prettiest. Alternatively, you can bind the object to the function (so the scope stays the same). This assumes your original code in someScopeScopedObject
:
someScopeScopedObject.init(someScopeScopedObject.myFunction2.bind(someScopeScopedObject));
Neither of these are pretty, and, really, that's because it is weird to externally feed a function belonging to an object as a callback to that object.
The best solution might be:
someScopeScopedObject.init(function() {
someScopeScopedObject.myFunction2();
});
Upvotes: 0
Reputation: 53958
The keyword this
refer's to the functions scope. Not the global scope. You declare a function called myFunction2
, the this
refers to the scope of this function and not the scope in which this function is declared.
It isn't like in languages, like C#, where this
refers to the current instance of the class, whether you are in one another method.
Upvotes: 3