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?
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.
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!
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();
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.