So with the following code, I proved to myself that nested functions do indeed gain a copy of the parameters of the outer function:
var o = {};
(function(a,b,c,x){
x.f = function(){
return a.toString()+b.toString()+c.toString();
}
})(7,4,2,o);
o.f();
The code yields
742
Which means that the o.f
function gains a copy of a,b, and c from the anonymous function. Otherwise, I would just get undefinedundefinedundefined
My questions are,
What you observe is called lexical scope. It means that the bindings of the variables in a certain scope in JavaScript are determined by where the variables appear in the code. It is always true, and it is true up to any level. The only main exception is the this
value, which is dynamically scoped rather than lexically scoped. Dynamic scope means variables in the function depend on how and when the function is called. (See Lexical Scoping and Dynamic Scoping.)
Example:
var o = {
a: function() {
var x = 5;
console.log(this, x);
function b() {
console.log(this, x);
}
b();
}
};
o.a();
The result of this example will be:
{Object o} 5
{window} 5
In other words, the first console.log
will log this
as a reference to the o
object, while the second console.log
will log this
as a reference to the window
object. However, both will log x
as being equal to 5
. The value of this
is window
when it is called in non-strict mode without a context. So this
is not scoped lexically, but other variables, like x
are. To read more about the behavior of this
see A Short Overview of this
.
To answer your questions directly:
Yes, it's true with the exception of this
and arguments
which change based on how the function is called. It doesn't have to be an object, all variables are lexically scoped.
You can go as deep as you want -- inner functions can always access the variables of their outer functions.
function a() {
var x = 1;
console.log('a:', x);
return function b() {
var y = 2;
console.log('b:', x, y);
return function c() {
console.log('c:', x, y);
};
};
}
var foo = a(); // => logs 'a: 1'
var bar = foo(); // => logs 'b: 1 2'
bar(); // => logs 'c: 1 2'
This is actually part of another topic referred to as closures, which occur when you return a function from within another function.
I've linked to a couple resources already. Another good one:
MDN: Functions and function scope (specifically the section on Nested Functions and Closures).
Also, you would be benefited from reading anything on closures, and you may also want to look up lexical scope.