Function declarations are "hoisted", which means they are moved to the top of the scope.
As a result, a new context for foo
is created within the local scope. Any later assignment of 10
will affect this localized scope and not the variable from the parent scope.
A similar behavior can be observed when declaring a block-local variable named foo
using the var
keyword:
var foo = 1;
function bar() {
var foo = 10; // effectively creates a function named foo in this scope
return;
}
bar();
console.log(foo); // output: 1
http://jsfiddle.net/GRMule/8F5K3/
Another example elucidating this concept:
var foo = 1;
function bar() {
console.log(foo); // due to hoisting, "function" will be the output
foo = 10; // overwrites the block-local foo
return;
function foo () {} // hoisted to the top of this scope, creating a new "foo" context
}
To prevent hoisting, you can use the var
method while declaring functions, though it's recommended to maintain code readability by avoiding reusing names like this:
var foo = 1;
function bar() {
console.log(foo); // undefined
foo = 10;
return;
var foo = function () {};
}
bar();
console.log(foo); // 1
http://jsfiddle.net/znrG2/
Using the var
word in a scope block causes the existence of that local context to be hoisted, not the value. Variables with the same name from the parent scope won't be accessible or affected in the current scope.
Functions and variables declared using this
, such as this.foo = function () {};
, do not hoist. Details here: http://jsfiddle.net/8F5K3/3/
Declaring functions or variables with this
doesn't overwrite variable contexts from the parent scope. This can be utilized to circumvent this behavior when needing to reuse the name "foo":
var foo = 1;
function bar() {
console.log(foo); // 1
foo = 10;
return;
this.foo = function () {};
}
bar();
console.log(foo); // 10
http://jsfiddle.net/znrG2/1/
Additional Resources