I was practicing some scenario and find a case:
Here is fiddle
According to closure bar function should have access to var x so I expected to alert 1 and condition get false due to if(!1) but it alerted undefined and condition get true and second alert is with value 10.
var x = 1;
function bar() {
alert(x);
if (!x) {
var x = 10;
}
alert(x);
}
bar();
So I am confused why it is prompting undefined?
According to hoisting in a particular scope you define a variable anywhere it is considered as defined at top always.
If it is due to hoisting effect it still have to alert 10 instead of undefined.
Hoisting causes a variable to be declared everywhere in the function, not defined.
On the first line of bar, since there is var x on line 3 of the function, the global x is masked and you see the local x (which is undefined since it hasn't been given a value yet).
On line 3 of bar, you have x = 10 which defines the variable. This is not hoisted.
On line 5, you alert it, and it is now defined.
Hoisting will make your code effectively work like this:
var x;
x = 1;
function bar() {
var x; //same as var x = undefined;
alert(x);
if (!x) {
x = 10;
}
alert(x);
}
bar();
Related
I am reading something on Variable Hoisting that I am not able understand exactly how to learn around it. I read W3C schools for the explanation. But, based on the sample code, I could not make what is hoisting.
code 1 [This is the code from w3c school]
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
var x = 5; // Initialize x
var y; // Declare y
elem = document.getElementById("demo"); // Find an element
elem.innerHTML = x + " " + y; // Display x and y
y = 7; // Assign 7 to y
</script>
</body>
</html>
But the above code still displays 'undefined' for the variable y.
If I change the code as follows then it works fine. But, this below code is usual and not the different one to understand 'hoisting'
<script>
var x = 5; // Initialize x
var y;
y = 7;
elem = document.getElementById("demo"); // Find an element
elem.innerHTML = x + " " + y; // Display x and y
</script>
Any help on this to understand 'Variable hoisting'?
(Note: I've added a brief discussion of ES2015's let and const at the end of this answer.)
Fundamentally, what variable hoisting means is that no matter where you see var in any given scope, it's as though it were at the very beginning of the scope. So these are all identical:
function foo() {
var a = 42;
}
function foo() {
var a;
a = 42;
}
function foo() {
a = 42;
var a;
}
function foo() {
var a;
a = 42;
var a;
}
They're processed by the JavaScript engine as though they were:
function foo() {
var a;
a = 42;
}
Here's an example actually using variable hoisting, and also giving an example of what I call The Horror of Implicit Globals (that's a post on my anemic little blog):
function foo() {
a = 42;
b = 67;
console.log(a); // 42
console.log(b); // 67
var a;
}
foo();
console.log(typeof a); // undefined
console.log(typeof b); // number?!
console.log(b); // 67?!
Why does b exist outside of foo? Because inside foo, these two lines do very different things:
a = 42;
b = 67;
The first line sets the local variable a, because we declared it. Yes, we declared it later, but we declared it.
The second line creates an implicit global variable b, because we never declared b anywhere in foo.
More (on my blog):
Poor, misunderstood var
ES2015 (aka "ES6") introduced let and const. They're handled slightly differently from var:
They have block scope rather than function or global scope.
The declaration is hoisted to the top of the block, but they don't get any default value at that point; they get initialized (with undefined or the value you provide) only when the declaration is reached in the step-by-step execution of the code.
Demonstrating point #1 (block scope):
function foo() {
{
let a = 1;
console.log(a); // 1
}
console.log(a); // ReferenceError: a is not defined
}
foo();
Demonstrating point #2: This would work with var, it doesn't work with let:
function foo() {
a = 42; // ReferenceError: a is not defined
let a;
}
foo();
The time between when the identifier is reserved (declaration) and when you can use it (initialization) is called the Temporal Dead Zone within which you can't use the variable.
Javascript Engine will execute code in two phases
Pre processing phase(or instantiation phase).
Execution Phase.
Pre processing phase(or instantiation phase)-
In Preprocessing phase, the script is scanned completely for all the declarations.
var - is the identifier to declare a variable.
So when var identifier is encountered, variable will be declared in the global scope.
The value of the variable is - undefined
Execution Phase-
In Execution Phase, the script is executed line by line. All the initializations will be done in this phase.
Example-1
For Below code snippet,
In Pre processing phase, Javascript engine will scan through the code line by line, when it encounters line "var a", it will declare variable a in the global scope.
In the Execution phase, at line "a=10", variable 'a' will be initialized with value 10. when it encounters console statements, value 10 will be printed.
a=10;
console.log(a); // 10
var a;
console.log(a); // 10
This is how variable hoisting works.
In Javascript, var x = 21; is broken into 2 parts: var x; and x = 21;.
The var x; part is always hoisted to the beginning of the enclosing function. The x = 21; part is left in its original place.
The same thing happens with function () {} declarations - this would be hoisted to the top of the enclosing function scope:
function pie () {
return 21;
}
just like the var.
A variable can be used before it is declared
JavaScript Initializations are Not Hoisted
Function Hoisting
As previously mentioned, function declarations are also hoisted. However, functions that are assigned to variables are not hoisted.
See below example
Function Declaration Overrides Variable Declaration When Hoisted
I am learning about variable hoisting in JavaScript, and found this behavior weird:
var x = 0;
(function () {
//Variable declaration from the if statement is hoisted:
//var x; //undefined
console.log(x); //undefined
if (x === undefined) {
var x = 1; //This statement jumps to the top of the function in form of a variable declaration, and makes the condition become true.
}
}());
Is it correct, that in this case, the statement makes the condition true so it can be executed?
Hoisting hoists only the declaration, but not the assignment. Your code is equivalent to:
var x = 0;
(function () {
//Variable declaration from the if statement is hoisted:
var x;
console.log(x); //undefined
if (x === undefined) {
x = 1;
}
}());
The if statement's condition expression evaluates to true and x = 1 is reached.
By the way ,if you declare a variables in a if statement ,No matter the if condition pass or not pass,the declaration is always hosited.For example:
console.log(a); //undefined , not respond ReferenceError ,it has been hoisted
if(true){
var a=1;
}
console.log(b); //same as above
if(false){
var b=1;
}
(function(){
var x = 23;
return function(){
var x = x;
return x;
}
}())();
Why does it return undefined instead of 23?
Shouldn't the var x = x; part be sufficiently unambiguous because the right hand side implicitly refers to the x in the outer scope?
The statement var x = x; doesn't see the variable x from the outer scope. The variable x inside the scope already exists before the assignment, and shadows the variable from the outer scope.
All variables in the scope are created before the code in the scope executes (hoisted), so it's the same as if you had:
(function(){
var x;
x = 23;
return function(){
var x;
x = x;
return x;
}
}())();
It actually doesn't matter where in the scope you declare the variables. You can declare them last in the code (although that would be a bit confusing), and the code still works the same:
(function(){
x = 23;
return function(){
x = x;
return x;
var x;
}
var x;
}())();
Shouldn't the var x = x; part be sufficiently unambiguous because the right hand side implicitly refers to the x in the outer scope?
No. All the scope of variables is determined before any assignments are performed.
there is a concept called variable hoisting.. i.e in short, just before executing the function, all variables that are declared inside function will be marked undefined. so it returns undefined.. Because of variable hoisting, you can define variable later but can use it before.. eg. function(){alert(x);var x;} will alert undefined but where as function(){alert(x);} throws error..
Given:
(function(){
var x = 23;
return function(){
var x = x;
return x;
}
}())();
The inner function only sees the inner x.
When entering an execution context, all declared variables are initialised, given the value undefined and placed on a kind of variable object before any code is executed (such as assignments). All outer variables are placed on a scope chain.
When resolving identifiers, the variable object is checked first, and only if not found there is the scope chain checked.
var x = 3;
(function (){
console.log('before', x);
var x = 7;
console.log('after', x);
return ;
})();
In the above code var X is initialized globally. So inside the function the first console.log should print "before 3" but i don't get it. The reason is that i am trying to re-declare the global variable.
Can somebody explain why this is happening?
In the above code var X is initialized globally. so inside the function the first console.log should print "before 3".
No, it should print before undefined, because var takes effect from the beginning of the function regardless of where you write it.
Your code is exactly the same as this:
var x = 3;
(function (){
var x;
console.log('before', x);
x = 7;
console.log('after', x);
return ;
})();
And of course, variables start with the value undefined.
Details: Poor misunderstood var
The JavaScript parser does Variable Hoisting when parsing your code. This means that any variable declaration will be moved to the top of the current scope, thus in your case, this code will get executed:
var x = 3;
(function (){
var x;
console.log('before', x);
x = 7;
console.log('after', x);
return ;
})();
So your local variable x gets declared at first with an initial value of undefined.
This should explain, why you get an "beforeundefined" for the first console.log().
The scope of a variable is much simpler than in other languages. It doesn't start at declaration but is either :
the function in which you have the declaration
the global scope if the declaration isn't in a function
MDN :
The scope of a variable declared with var is the enclosing function
or, for variables declared outside a function, the global scope (which
is bound to the global object).
You can imagine that all variable declarations are moved to the start of the scope (the function). So this is exactly like
var x = 3;
(function (){
var x;
console.log('before', x); // now undefined
x = 7;
console.log('after', x); // now 7
return ;
})();
Be careful to understand what is the exact scope (the function, not the block) :
var x = 3;
(function (){
console.log('before', x); // this is undefined !
if (true) {
var x = 7;
}
return ;
})();
For this snippet, I'm not surprised global variable 'a' evaluates to be 5.
http://jsfiddle.net/MeiJsVa23/gZSxY/ :
var a = 10;
function func(){
a = 5;
}
func(); // expect global variable 'a' to be modified to 5;
alert(a); // and this prints out 5 as expected. No surprise here.
But how come for this code snippet, global variable 'a' evaluates to be 10 and not 5? It's as if the a = 5 never happened.
http://jsfiddle.net/MeiJsVa23/2WZ7w/ :
var a = 10;
function func(){
a = 5;
var a = 23;
}
func(); // expect global variable 'a' to be modified to 5;
alert(a); // but this prints out 10!! why?
This is due to variable hoisting: anything defined with the var keyword gets 'hoisted' to the top of the current scope, creating a local variable a. See: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
So, there are two things are going here: hoisting and shadowing.
Because the first one, variable declarations are "hoisted" to the top, so your code is equivalent to:
var a = 10;
function func(){
var a;
a = 5;
a = 23;
}
And because the second one, you're "shadowed" the global variable a with a local ones, so the changes are not reflected to the global a.
This is called "variable hoisting". var declarations (and function() declarations) are moved to the top of their scope.
This has to do with hoisting.
In the function, a local variable with the same name is declared. Even though it happens after your modification, it is deemed to have been declared before it - this is called hoisting.
Local variables hoist for declaration but not value. So:
function someFunc() {
alert(localVar); //undefined
var localVar = 5;
}
Functions, if declared with function name() {... syntax, hoist for both declaration and value.
function someFunc() {
alert(someInnerFunc()); //5
function someInnerFunc() { return 5; }
}
var a = 10; //a is 10
function func(){
a = 5; //a is 5
var a = 23; // a is now in local scope (via hoisting) and is 23
}
func();
alert(a); // prints global a = 10
Presumably, the statement var a = 23 creates a local variable for the whole scope. So the global a is shadowed for the entirety of func(), not just for the lines below the statement. So in your second snippet, a = 5 is assigning to the local variable declared below.