Here's an explanation of what's happening:
When you wrap code in a function, you get what's called function scope. This means that the scope within the function belongs to the function and not to a scope above or outside of it (whichever way you want to look at it).
A closure allows an expression (typically, a function, as MDN states) to have it's own scope while sharing the scope of it's outer or higher scope.
So, let's look at an example:
// This represents the global, or window, scope.
// Analogous to window.outer_var.
var outer_var = 'outer var';
function outer_func() {
// New scope! Local only to outer_func and those
// expressions (functions) *enclosed* by
// `outer_func(){...}, e.g. inner_func(){...}.
var inner_var = 'inner var';
// Only outer_func() or inner-enclosed (to
// inner_func()'s definition) functions can
// access inner_func().
function inner_func() {
// Another new scope! Can access inner_var
// and inner_func_var (below). outer_func()
// canNOT access inner_func_var, though.
var inner_func_var = 'inner func var';
}
}
outer_func(); // Of course, it's in scope and accessible.
inner_func(); // This will cause ReferenceError: inner_func is not defined error.
Simply as it is (no wrapping context, with a closure), var outer_var
is created with the global or window scope. It may be accessed in all of the following:
console(window.outer_var);
function outer_func() {console.log(outer_var);}
function inner_func() {console.log(outer_var);}
No matter where inner_func's defined.
Here, #2/3 are analogous to:
function outer_func() {console.log(window.outer_var);}
function inner_func() {console.log(window.outer_var);}
Or global this
:
function outer_func() {console.log(this.outer_var);}
function inner_func() {console.log(this.outer_var);}
Now, inner_var
is accessible from the following:
function outer_func() {console.log(inner_var);}
function inner_func() {console.log(outer_var);}
Only from within outer_func()
.
inner_func()
may also only be accessed within outer_func()
, because it belongs to the outer_func()
scope, and thus is not visible/accessible outside of outer_func()
*.
Lastly, inner_func_var
is only accessible by:
function inner_func() {console.log(inner_func_var);}
Only within outer_func()
.
To access your three
variable, you have three choices:
- Make
three
globally accessible (globals are generally discouraged as they may easily introduce difficult to resolve bugs when one is overwritten by some other code).
- Return
three
from your test()
function. In this case the value is accessed, not the actual variable within the function.
- Create a property as @logic8 demonstrates, so it may be accessed as a property of an object.
* This isn't entirely true. outer_func()
could export a reference to the function out of scope with return inner_func;
. This is a more advanced concept, though, and won't be addressed here in depth. Here is an example.