I am puzzled as to why the final alert shows a value of 1 instead of 10.
This discrepancy occurs due to the foo
variable within the function bar
:
foo = 10;
...being associated with the function declaration later in that same function:
function foo(){}
...rather than the foo
variable outside of that function. Specifically, this is referencing:
var foo=1;
function bar(){
foo=10;
return;
function foo(){}
}
bar();
alert(foo);
The reason for this behavior can be attributed to two factors:
Function declarations are immediately processed upon entering the containing scope (in this case, the call to bar
), before any step-by-step execution of code within the function. This phenomenon, sometimes referred to as "hoisting," ensures that all declarations are handled beforehand regardless of their placement in the code.
Function declarations effectively create variables with identical names as the functions themselves. Therefore, the foo
referenced in the function declaration acts as a variable with that name - thereby allowing assignment of new values to these "variable-like things."
When the provided code runs, here's the sequence of actions performed by the JavaScript engine:
Creates a variable named foo
with an initial value of undefined
.
Defines the bar
function, registering it as an in-scope symbol within the current context and associating it with the function definition.
Begins executing the code step-by-step within this scope.
Sets the value of foo
to 1
.
Invokes the bar
function.
Establishes the foo
function relevant to the bar
call, creating it as an in-scope symbol during the function invocation.
Initiates the step-by-step processing within this nested scope.
Assigns the value 10
to the local foo
, which previously referenced the function itself.
Exits from the function.
Executes the alert
function using the foo
within this specific scope, still holding the original value of 1
.
Further insights into this intricate process can be found in Section 10.4.3 of the ECMAScript specification along with its related sections.
* "variable-like thing": In JavaScript, every execution context (comprising the global context and all contexts resulting from function calls) maintains a binding object to manage various identifiers and their corresponding values within that specific context. The binding object incorporates properties for each variable, function declaration, and other essential elements like the arguments
pseudo-array and the function name referring back to itself. Consequently, changing the value of foo
within bar
overrides the reference to the foo
function declared inside bar
rather than modifying the outer-scoped variable. Essentially, foo
behaves akin to a local variable within bar
due to the function declaration.