This question already has answers here:
Surprised that global variable has undefined value in JavaScript
(6 answers)
Closed 3 years ago.
I am new to coding and cannot figure out the following code. If anyone can give me a hand I will deeply aprreciate!!
function a() {
function b() {
console.log(x);
}
var x = 2;
b();
}
var x = 1;
a();
When I run this code it makes perfect sense that the console is 2. Super!
But when I run this code:
function a() {
b();
function b() {
console.log(x);
}
var x = 2;
}
var x = 1;
a();
When this code runs, I would have thought that the console answer would be 2 as well! but I get undefined as the answer. At least I would have thought that 1 could be the answer in case it was not 2, but never ever: undefined.
Can anybody please give me a hand?
Many thanks!
var declarations are hoisted.
That means that these declarations are moved to the top of the current scope (function) at compile time (before the code runs).
Hoisting does move the variable declaration, but does not move the variable assignment.
Thus, this code:
doSomething();
var variable = value; //Declaration with assignment
is transformed to:
var variable; //Declaration
doSomething();
variable = value; //Assignment
So, your code is identical to the following:
function a() {
var x; //x is now undefined
//Function declarations are hoisted as well:
function b() {
console.log(x);
}
b(); //x is still undefined now...
x = 2; //x is now 2, but your console.log has already run.
}
var x = 1; //This line doesn't affect your code, as the x you log is in different scope, and the internal x shadows this one.
a();
so x is undefined in your second example because of the fact that you initialized x (i.e. var x = 2) after you called function b (i.e. b()). That means the program does not know what x is yet when you called function b so when you do call b() you are trying to print something you have not yet defined to the program.
The first example works because x is defined before the function call to b
Related
This question already has answers here:
Can you clarify this JavaScript variable hoisting behavior?
(3 answers)
Closed 5 years ago.
var x = 3;
function func(randomize) {
if (randomize) {
var x = Math.random();
return x;
}
return x;
}
console.log(func(false));
As you can see from above code, if statement never be true but the x value is undefined, i would like to understand how variable declaration works in javascript. Any references also be helpful.
Update:
Can anybody explain why variable was re-declared to undefined and how it is related to hoisting in javascript
Because func is in essence:
function func(randomize) {
var x;
if (randomize) {
x = Math.random();
return x;
}
return x;
}
Variables in JavaScript have function scope, not block scope with which you might be familiar from other languages. This results in the hoisting behavior you observe:
What does happen is that variable and function declarations are put into memory during the compile phase, but stays exactly where you typed it in your coding.
...
JavaScript only hoists declarations, not initializations. (emphases mine)
That is, even though inside func you declare x in the if block, during compile time its declaration is moved to function level where it shadows x in global scope. However, it is only initialized if the argument to func is true which leads to the behavior you observe.
See also let:
"use strict";
var x = 3;
function func(randomize) {
if (randomize) {
let x = Math.random();
return x;
}
return x;
}
console.log(func(false));
console.log(func(true));
You define a new variable var x in your function and thus overwrite the outer variable x.
I don't understand a part of the accpeted answer of this OP:
Javascript function scoping and hoisting
Writer says:
"
Also, in this instance,
function a() {}
behaved the same as
var a = function () {};
".
What I know is that function expression is different than function declaration, at least for hoisting. Why are they similar in this case?
Why are they similar in this case?
Because var is hoisted (but not set), like a function declaration is hoisted, meaning that there is an a in the local scope before a = 10; is evaluated, so the global a never gets modified - the identifier lookup finds the local a first so sets that
Related parts of the other question
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
Why is a === 1?
That the answer was trying to say was that b is equal to
function b() {
function a() {}
a = 10;
return;
}
Similar to
function b() {
var a = function () {};
a = 10;
return;
}
i.e. there is an identifier a defined in b, so
function b() {
var a = 10;
return;
}
And now, obviously, the global a will not be modified by b
Please note that the position of the var isn't really important, just that it's there, the following will produce the same behaviour
function b() {
a = 10;
return;
var a;
}
The difference is that the first line is defined at run-time, whereas second line is defined at parse-time for a script block.
Look at the full answer on stack, here : var functionName = function() {} vs function functionName() {}
How will the code look after hoisting is done by js?
jsFiddle shows it prints 1, but how is that true?
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
This is what I have come up with:
var a; //hoisted var declaration
function b() { //hoisted function declaration
function a() {} //hoisted function declaration
a = 10;
return;
}
a=1;
b();
alert(a);
This is expected behaviour.
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
This all has to do with the scope and when a function is defined. Declaring a function with the codeword function first
function a(){};
will add the function to the scope at parse time. I.E It is defined before the first line in b(). What is happeing is that you define a to be a loal variable inside b. This will make the global variable a unreachable from within b. a will be defined and manipulated locally within the scope of b and leave the global a untouched.
Equivalient code will be
var a = 1;
function b() {
var a = function() {}
a = 10;
return;
}
b();
alert(a);
After some experimentation, i've reached to the conclusion that having the same Global variable and local function name is confusing the JS Engine..
So what you are doing by a = 10 is changing that function declaration or something.. it's not affecting the global variable a. But, changing the name of global variable and keeping it different from the inner local function will give the expected results:
var c; //hoisted var declaration
function b() { //hoisted function declaration
function a() {alert('in');} //hoisted function declaration
c = 10;
return;
}
c=1;
alert(c); //1
b();
alert(c); //10
See the DEMO here
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
There is nothing confusing here. Moving all declaration to the top, your code is the same as:
var a; //global a
var b = function(){
var a = function(){}; //local a
a = 10; //still referring to local a
return;
};
a = 1; //referring to global a
b();
alert(a); //referring to global a
Both a aren't the same. I believe it is quite obvious.
The first code example given appears to be identical to one on Ben Cherry's adequately good site. This goes into more detail on the way scoping works in JavaScript (primarily - it's function-level, not block-level), and ends with the following statement, attributed directly to the ECMAScript Standard:
If the variable statement occurs inside a FunctionDeclaration, the variables
are defined with function-local scope in that function, as described
in section 10.1.3. Otherwise, they are defined with global scope (that
is, they are created as members of the global object, as described in
section 10.1.3) using property attributes.
...
A Block does not
define a new execution scope. Only Program and FunctionDeclaration
produce a new scope.
This hopefully explains why the code you include works the way it does - there is no "way the code looks after hoisting", there's just a simple (and, common) misunderstanding about how scope works in JavaScript.
This question already has answers here:
Javascript function scoping and hoisting
(18 answers)
Closed 8 years ago.
I am kind of novice in JavaScript, I really don't quite understand why the below code return 1 instead of 10:
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
The running code: http://jsfiddle.net/smMtU/
If I rem the line function a() {}, it returns 10 as expected. This code got from this post to explain the concept scoping and hoisting in JavaScript. Maybe I am missing something while reading this post?
Please anyone could point out the concept behind this code?
Due to hoisting, your code is equivalent to
var a = 1;
function b() {
var a = function() {};
a = 10;
}
b();
alert(a);
Inside b you're not changing the external a but an internal one.
This declaration creates a scope for the function a in the current scope before the execution.
When the function b is called and this line below is executed
a = 10;
there's already a scope a created inside the function b
So this becomes equivalent:
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
to this:
var a = 1;
function b() {
var a = function(){}; //scope created before
a = 10; //'a' already exists in local scope, just replace it.
return;
}
b();
alert(a); // global 'a' remains intact
This question already has answers here:
Javascript function scoping and hoisting
(18 answers)
Closed 8 years ago.
I was reading this article and I have some questions please:
considering this code :
1: var a = 1;
2: function b () {
3: a = 10;
4: return;
5: function a() {}
6: }
7: b();
8: alert(a);
this will alert 1. ( my question is why ? )
the article states its related to Name resolution.
Name resolutions (according to the article ) is being determined by this order:
1. Internal mechanisms of language: for example, in all scopes are available “this” and “arguments”.
2. Formal parameters: the functions can be named as the formal parameters, which scope is limited to the function body.
3. Function declarations: declared in the form of function foo() {}.
4. Variable declarations: for example, var foo;.
line #3 suppose to change the value of the global a.
but the function a(){...} have a priorty over the inside a declaration ( If i understood correctly)
and thats why is alerts 1
p.s. if i remove line #5 , it will alert 10.
In general, if a name is already defined, it will never be redefined
by another entity with the same name. That is the function declaration
has a priority over the declarations of the variable with the same
name. But this does not mean that the value of a variable assignment
does not replace the function, just its definition will be ignored.
I dont understand that part :
But this does not mean that the value of a variable assignment does
not replace the function
so 2 questions please :
Did I understand correctly the reason for alerting 1
What does the above line means ? (the misunderstood part)
thanks.
Did I understand correctly the reason for alerting 1
Yes
"But this does not mean that the value of a variable assignment does not replace the function"
What does the above line means ? (the misunderstood part)
It just means that although a function with name a is already defined, a = 10 is still going to be executed, i.e. after that line a does not refer to a function anymore but to 10.
I assume they wanted to relax the previous statement a bit and avoid that people incorrectly think that because the function declaration is executed first, the assignment would not take place anymore.
Function and variable declarations are hoisted to the top of the scope. So the code is equivalent to:
1: var a = 1;
2: function b () {
3: function a() {}
4: a = 10;
5: return;
6: }
7: b();
8: alert(a);
function a() {...} creates a symbol (variable) a in the local scope and its value is the very same function. The next line, a = 10;, then assigns a new value to that symbol, namely a number.
var a = 1;
function b () {
function a() {} // creates a new local symbol `a`, shadowing the outer `a`
// until here, `a` refers to the function created
// created by the above declaration
a = 10; // now a new value is assigned to the local symbol/variable `a`
// from here on, `a` is `10`, not a function
return;
}
b();
alert(a);
var a = 1;
function b () {
var a = 10;
}
b();
alert(a);
does the above example make sense to you? Yes? Good, then you understand the difference between local and global scope...
var a = 1;
function b () {
a = 10;
var a;
}
b();
alert(a);
Does this example make sense to you? Yes? Then you understand that it does not matter where a variable is declared in a function, it will always be declared when first entering the function.
var a = 1;
function b () {
a = 10;
var a = function() { };
}
b();
alert(a);
Now, does this example make sense? Yes? Then you understand dynamic typing. A variable can be assigned a function as a value and then can be overwritten with a integer such as 10.
var a = 1;
function b () {
a = 10;
return;
function a() { }
}
b();
alert(a);
Now your example should make sense because we are just changing the way we declare a, but its the same thing.
From my understanding of hoisting, both variable declarations and function declarations are hoisted. Therefor, here's what's happening:
var a; // a is declared (hoisted)
function b () { // function declaration (hoisted)
function a () {} // function declaration (hoisted)
a = 10; // an assignment to the local a that was hoisted, not the outer a
return;
}
a = 1; // initialization (not hoisted)
b(); // hoist inside b's scope causes an inner a to be modified
alert(a); // alerts 1 since the outer a was never modified