I'm following along YDKJS Scope & Closures, specifically the Appendix C - Lexical this section where the following code is presented:
var obj = {
id: "awesome",
cool: function coolFn() {
console.log(this.id);
}
};
var id = "not awesome";
obj.cool(); // awesome
setTimeout(obj.cool, 100); // not awesome (because this refers to window and window and it will take the global id)
Then he proposes the following solution (the first of a couple that he offers):
var obj = {
count: 0,
cool: function coolFn() {
var self = this;
console.log(self); // This will still be window if invoked from setTimeout
if (self.count < 10) {
setTimeout(function timer() {
self.count++;
console.log("awesome?");
}, 100);
}
}
}
obj.cool(); // awesome?
The idea is that you bind this to a lexically-scoped variable called self so we can sort of abstract away the confusing behavior of this, and then he goes on to explain why there are better solutions (for instance, just understanding how this works, which is the topic of the next book in his series). However, for this particular offered solution, I don't see how it solves anything? If we call setTimeout(obj.cool, 500);
outside of obj, won't the same problem arise as in the first example? obj.cool() will run and set self equal to the global window object and break. Am I missing something? What is the point of declaring a lexically-scoped self variable if its definition depends on the state of this. For instance, if we use setTimeout, then self definitely doesn't refer to "self". I've also noticed that (at least in the environment I work in), you don't even need to state the var self = this line, you can just use the word "self" out of the box with the same effect.
Edit: To make the question more precise, let's consider the following snippet:
var obj = {
id: "awesome",
cool: function coolFn() {
var self = this;
console.log(self.id);
}
};
var id = "not awesome";
obj.cool(); // awesome
setTimeout(obj.cool, 100);
This snippet is identical to snippet 1 except that it uses the var self = this
mechanism and logs self.id
instead. However, it has the exact same output as the first snippet. What problem is this solving if it doesn't solve the problem of correcting the output?