I am following a tutorial that is showing the factory pattern to create objects in javascript. The following code has me stumped as to why it works.
6-2.htm
the first commented line seems proper to me (using the this
keyword in the showLabel function). i'm not sure how using obj in its place is working. obj would have to reference a global variable somewhere because within that function when its run there is no obj defined, right? since i make 2 objects, its not just luck in this case that both get displayed fine, the older values for obj's contents are stored and referenced properly. but how? if i uncomment the second comment then it breaks and i understand why, now im explicitly telling js that i'm talking about a local variable and there is none.
Answer
Welcome to the world of closures. You are right to sense what you feel to behave as if it's a global but not quite global. That's how closures behave.
Basically in javascript when a function returns not all local variables are necessarily garbage collected/freed like in Java or C. If there is a reference to that variable then that variable survives in the scope of the function where it is defined.
Technically the mechanics are different and some people try to explain it that way and end up confusing a lot of other people. To me, closures are a sort of 'private' global variables in that like globals, they are shared accross functions but they are not declared in the global scope. It's just like what you describe feeling upon encountering this feature.
Here are some of my other answers here on stackoverflow related to javascript closures which I believe are worth reading:
Hidden Features of JavaScript?
Please explain the use of JavaScript closures in loops
Or you can just google the phrase "javascript closure" to explore the subject.
Additional answer.
As for the explanation of why this
works in your code (as opposed to *cough* attempting to correct your code so that this
would work even though it works in the uncorrected version *cough* ;-):
Javascript has late bindings. Very late, very-very late. Not only is this
not bound during compile time, it is not even bound during run time. It is bound at execution time - that is, until a function is called you can't know what this really points to. The caller basically gets to decide what the value of this
is, not the function where this
is used.
Some funky javascript late binding maneuvers:
function foo () {
alert(this.bar);
}
var bar = "hello";
var obj = {
foo : foo,
bar : "hi"
};
var second_obj = {
bar : "bye"
};
foo(); // says hello, 'this' refers to the global object and this.bar
// refers to the global variable bar.
obj.foo(); // says hi, 'this' refers to the first thing before the last dot
// ie, the object foo belongs to
// now this is where it gets weird, an object can borrow/steal methods of
// another object and have its 'this' re-bound to it
obj.foo.call(second_obj); // says bye because call and apply allows 'this'
// to be re-bound to a foreign object. In this case
// this refers to second_obj
In your code, this
conveniently refers to the object invoking the function as its method which is why it works even though you are apparently not using supposedly correct constructor syntax.
No comments:
Post a Comment