I don't understand why the value of foo is undefined in the following code:
var foo = 1;
function bar() {
if (false) {
var foo = 10;
}
alert("Foo is " + foo);
}
bar();
Result : Foo is undefined.
https://jsfiddle.net/yk7ae9b0/
Whereas these variations behave as expected.
var foo = 1;
function bar() {
if (true) {
var foo = 10;
}
alert("Foo is " + foo);
}
bar();
Result : Foo is 10
var foo = 1;
function bar() {
if (false) {
// var foo = 10;
}
alert("Foo is " + foo);
}
bar();
Result: Foo is 1
Any help will be really appreciated.
Your var foo is not defined where you think it is. Variables in JavaScript are scoped to the function that uses them, not to the block where they are declared. As such, the code you had:
function bar() {
if (false) {
var foo = 10;
}
alert(foo);
}
Is actually interpreted by the JS engine as if it were written as:
function bar() {
var foo;
if (false) {
foo = 10;
}
alert(foo); // foo was never assigned a value!
}
So, when the alert triggers, you have an undefined variable foo that shadows the global foo you declared outside your function.
(This also affects things like for(var i=...) ... -- that var i is function scoped, and will be a declared variable everywhere inside the function, not just inside your for-loop)
Related
This question already has answers here:
Javascript variable and function hoisting
(3 answers)
Closed 6 years ago.
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = 11;
}
console.log(typeof bar());
typeof bar returns function?!
why not number?
JS functions are executed in two passes three passes. First, the engine walks through the code, looks for function declarations and hoists them (=moves them to the top), second, it hoists variable declarations (unless the same name is already hoisted), finally it runs the "normalized" code.
In your snippet, the engine picks function foo and moves it to the top of the function. The subsequent var foo is ignored.
This results in the following "normalized" code:
function bar() {
function foo() {}
return foo;
foo = 10;
foo = 11;
}
which explains your results.
Reference: Declaration Binding Instantiation, notice steps 5 and 8.
return foo just references to function foo() {} so it's returning Function
function bar() {
return foo; // function foo() {}
foo = 10;
function foo() {}
var foo = 11;
}
alert(typeof bar()); // function
another scenario
function bar() {
return foo; // returns foo undefined as no value is assigned
foo = 10;
var foo = function () {} // referenced to variable
var foo = 11;
}
alert(typeof bar()) // undefined
here it will return number
function bar() {
foo = 10;
return foo; // 10
function foo() {}
var foo = 11;
}
alert(typeof bar()); // number 10
this too will return a closure function which returns a number
function bar() {
foo = 10;
return function () {
return foo
}
var foo = 11;
}
alert(typeof bar()()); // number 10
You messed with return :).
It is not about the priority. It is about the thing you last return from the function. Alter them and see. You get number.
function bar() {
function foo() {}
var foo = 11;
return foo;
foo = 10;
}
alert(typeof bar());
This gives you number.
The reason for this behavior is due to Hoisting in javascript.
When javascript is interpreted, any variable definition is processed first, so in the scope of your function, the actual order of the call is something like this:
function bar {
var foo = 11;
function foo() {}
return foo;
}
The hoisting positions the var foo = 11 declaration first, and then the foo is overwritten by the foo named function. hence return foo returns the function itself, not the numeric value.
This is a good starting point to understand hoisting
The return statement prevents the number assignments from executing, but the function declaration doesn't care.
function bar() {
return foo;
foo = 10; //assignment is never executed
function foo() {} //function definition happens even if code is not executed
var foo = 11; //assignment is never executed
}
console.log(typeof bar());
To test this out, comment out the function foo() {} line. You'll see that bar() returns undefined. The assignment statements define foo even if the statements are not executed, but they don't clobber the value of foo until they are executed (thus leaving the function definition in place).
Fiddle with the code:
https://jsfiddle.net/vwm31faq
Function gets Hoisted to the top of the current scope, hence you code at execution time would look like
function bar() {
var foo;
function foo() {}
return foo;
foo = 10;
function foo() {}
foo = 11;
}
console.log(typeof bar());
Why is the result of the following code 1 and not 10? Why doesn't the function bar() change the value, even though there is a return statement.
var foo = 1;
function bar() {
foo = 10;
return;
function foo() {}
}
bar();
alert(foo);
This is because function definitions are hoisted to the top of their scope, so the foo assignment inside bar() is actually referring to the local function that has an empty body.
You can read more about this here
This is because while compiling the foo function declaration inside bar moves on the top of the bar. Like this
var foo = 1;
function bar() {
function foo() {}
foo = 10;
return;
}
bar();
alert(foo);
Read about hoisting in JS.
And here in the "var hoisting" section
I am studying the execution context from Javascript. But i dont understand why the "function foo" not will be over written by the "var foo".
I hope someone can explain this,
thank you for your respons.
function ace() {
console.log(typeof foo); // function pointer
console.log(typeof bar); // undefined
var foo = 'hello',
bar = function() {
return 'world';
};
function foo() {
return 'hello';
}
var foo = 'hello';
}
ace();
why the "function foo" not will be over written by the "var foo".
foo is overwritten at the line where foo is re-defined
function ace() {
console.log(typeof foo); // function pointer
console.log(typeof bar); // undefined
var foo = 'hello',
bar = function() {
return 'world';
};
function foo() {
return 'hello';
}
var foo = 'hello';
console.log(foo);
try {
foo()
} catch(e) {
console.log("catch:", e.message)
}
}
ace();
But i dont understand why the "function foo" not will be over written by the "var foo".
The var declaration does not overwrite the function declaration. They both declare the same variable, and because of the function declaration it is initialised with a function. It is only the assignment that will overwrite the value.
If you take hoisting into account, your script will behave like
function ace() {
var foo, bar;
var foo = function() {
return 'hello';
}
var foo;
console.log(typeof foo); // function
console.log(typeof bar); // undefined
foo = 'hello';
bar = function() {
return 'world';
};
console.log(typeof foo); // string
foo = 'hello';
}
ace();
Can anyone explain to me why if statement inside of bar has foo us undefined?
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();
// This foo is at the global level.
var foo = 1;
function bar() {
// the compiler puts in this line:
var foo;
if (!foo) {
// and the var here doesn't matter.
foo = 10;
}
alert(foo);
}
bar();
The given code will be parsed like this:
var foo = 1;
function bar() {
var foo;
if (!foo) {
foo = 10;
}
alert(foo);
}
bar();
The local foo is hoisted to the top of the function since JS only has function scope and no block scope. The "hoisted" variable will take precedence over the foo defined outside the function, which is why the variable is undefined in your if statement.
Don't first class functions mean that they behave as variables? Clearly they don't behave exactly like variables though, since this:
console.log(foo);
var foo = 'bar';
...doesn't work, whereas this:
console.log(foo());
function foo() {
return('bar');
}
...does.
That said, this:
console.log(foo());
var foo = function() { return 'bar'; };
doesn't work, which is more consistent.
What gives?
What you're experiencing is called hoisting. When using a function declaration like:
function foo() {}
foo will be moved to the top of the closest scope (function).
On the other hand when you use a function expression or function assignment like:
var foo = function() {}
the variable foo will be moved to the top but the assignment will occur when is needed.
Learn more
Because you don't compare the same thing. In your example - you compare function declaration function foo()... with variable declaration and assignment in var foo = 'bar';
A more correct comparison would be of:
console.log(foo);
var foo = 'bar';
with
console.log(foo());
var foo = function() {
return 'bar';
}
The functional declaration is interpreted differently due to the way hoisting works. Hoisting moves all declarations to the top of the closest scope, while leaving assignments in their place.
Function declaration is special in that sense, since it's both declaration and expression/assignment in one statement and thus hoisted together.
As an example: you can look at expressions like:
console.log(foo);
var foo = 'bar';
as this:
var foo;
console.log(foo); //prints undefined
foo = 'bar';
and
console.log(foo());
var foo = function() {
return 'bar';
}
as this:
var foo;
console.log(foo());
foo = function() {
return 'bar';
}
Function declarations are automatically bumped to top of the scope in JS
console.log(foo());
function foo() {
return('bar');
}
is actually interpreted as
function foo() {
return('bar');
}
console.log(foo());
the second bit of code is working that way, because foo is variable, not a function (it just happens to have an anonymous function as a value). Variables are also bumped to top, so
console.log(foo());
var foo = function() { return 'bar'; };
becomes
var foo; //empty variable
console.log(foo()); //undefined
foo = function() { return 'bar'; }; //creates a function without name and assigns it to foo
Function declaration and variable declaration will always be moved to the top of their scope.
console.log(foo());
function foo() {
return 'bar';
}
is interpreted as:
function foo() {
return 'bar';
}
console.log(foo());
console.log(foo());
var foo = function () {
return 'bar';
};
is interpreted as:
var foo;
console.log(foo());
foo = function () {
return 'bar';
};