explanation on hoisting in javascript [duplicate] - javascript

This question already has answers here:
Javascript function scoping and hoisting
(18 answers)
Closed 7 years ago.
I am learning javascript hoisting and came across a scenario for which I need a bit more explanation. Below is the program that I have
test();
console.log("The value of data is "+data);
function test(){
console.log("Hello");
}
var data = 15;
If I run the above program in JsFiddle, I am getting the below output:
Hello
The value of data is undefined
Is the data hoisted? I am seeing the console as undefined so I presume that the data variable is hoisted.
Is variable hoisting only inside the function? In the above program, if the data is hoisted does that imply that the data variable hoisted even at global level?
The above program prints the text Hello when I define the function without a variable. So is this referred to as function hoisting or is it global function?
If the var data = 15 is changed to data = 15, then I get the error: Uncaught ReferenceError: data is not defined. Why is it behaving differently than in case of function?
Please help me understand what I am missing here.

Is the data hoisted? I am seeing the console as undefined so I presume that the data variable is hoisted.
The binding is hoisted and it's always initialized to undefined, this means data exists but there hasn't been an assignment yet.
Is variable hoisting only inside the function? In the above program, if the data is hoisted does that imply that the data variable hoisted even at global level?
Hoisting happens either way, but variables defined inside inner functions aren't hoisted to the script/function that contains them. So var a inside a function fn won't be available on the outer scope.
The above program prints the text Hello when I define the function without a variable. So is this referred to as function hoisting or is it global function?
Javascript understands function differently depending on the context. When you define a function like this:
function fn(){
}
It's considered a function declaration, when you write something like this:
var fn = function(){ };
The function part is considered a function expression. The expression is evaluated when it reaches that point in the script. While the declaration is hoisted to the top. They both produce a fn in their relevant scope, it's just that one is hoisted the other one isn't.
If the var data = 15 is changed to data = 15, then I get the error: Uncaught ReferenceError: data is not defined. Why is it behaving differently than in case of function?
When you removed the var portion, the binding is no longer hoisted. In non-strict mode, the binding will be available after the assignment. In strict mode not only does reading data will fail, but also the assignment will fail.

Your program :
test();
console.log("The value of data is "+data);
function test(){
console.log("Hello");
}
var data = 15;
is actually executed as though you had written :
var data; // declaration of data hoisted
function test(){ // Also function definition
console.log("Hello");
}
test(); // Show 'Hello'
console.log("The value of data is "+data); // Data still has no value!!
data = 15; // Now data has the value 15.
In short the declaration of variables and functions are hoisted, the
assignment of values remains where you write them.
Now as an exercise, what does this produce :
test();
var test = function test(){definition
console.log("Hello");
}
console.log("The value of data is "+data);value!!
data = 15;
and why?

Related

Can we access a variable declared using 'var' keyword inside a block? [duplicate]

This question already has answers here:
How JS hoisting works within functions?
(4 answers)
Closed 2 months ago.
A variable is declared using 'var' keyword inside a block ( {...} ). Can we access that variable outside the block?
I searched on several websites and the answer was 'yes'. 'Yes we can access the variable' it said.
But when I executed this on a browser console it said "the variable is not defined". Any thoughts why this is so?
Here's the screenshot of the same
I expected it to give 12345.
A variable is declared using 'var' keyword inside a block ( {...} ). Can we access that variable outside the block? I searched on several websites and the answer was 'yes'.
tldr; It's more precise to say Yes, unless that block is a function body.
var scopes a variable to the nearest function.
The body of the function (excepting some arrow functions) is a block.
Not all blocks are associated with functions.
{
var inBlock = 1;
}
console.log(inBlock); // This logs 1
function aFunction() {
var inFunction = 2;
}
aFunction();
console.log(inFunction); // This triggers a reference error
You can access the variable but that doesn't necessarily mean your variable will actually have a value before passing through said block.
var will be known throughout the entire function. So if you declare var x at the end of your function (or in an if-block nested in a while in another while) and assign it there, you will be able to call it at the start of the function, but the value will be "undefined" since it hasn't been assigned a value yet at that point of the execution.
Hence why var needs careful consideration on usage to make sure you actually need said variable outside the block where you're using/initializing it.
for-loops are (in my opinion) easiest to explain this with:
for( var i = 0; i < arr.length; i++ ) {
// do something
};
The variable i here will actually be known OUTSIDE the for-loop. It will be undefined before going through the for loop and will have the value of the last iteration after the for loop. (As oppposed to using let which will make it so variable i is not known outside the for-loop)
Variables declared with var has global and function scope but does not have block scope. Which means these variables are only accessible inside a function or globally.
// if we try to access it from function scope, it is not accessible
function greeting() {
var sayHi = "Hello"
return sayHi
}
console.log(sayHi) // sayHi is undefined. Because it has function scope
// if we try to access it from block scope, it is accessible.
if (1 < 2) {
var sayBye = "Bye"
}
console.log(sayBye) // prints 'Bye', because it has no block scope
After execution of the function, the variable will no longer be available and it will be referencing the globally scope which don't have your variable.

Why does XMLHttpRequest variable become 'undefined'? [duplicate]

I have been wondering for a while if I can use a variable in JS before it is defined,
such as the following:
var country = "USA";
switch (country) {
case "USA":
country = i;
case "blach":
//not finished yet
}
/*
put a whole
bunch more code here
*/
var i = 10;
Is this valid? Is it allowed? And if so, what is the technical term for it?
This is a technique used by the JavaScript engine called hoisting. The parser will read through the entire function before running it, and any variable declarations (i.e. using the var keyword) will be executed as if they were at the top of the containing scope. So your code behaves like:
var country;
var i;
country = "USA";
switch (country) {
case "USA":
country = i;
case "blach":
//not finished yet
}
i = 10;
So, i is declared throughout the entire scope, but its value is undefined until the i = 10 statement runs.
In ECMAScript terms, when a function is invoked, the function's new lexical scope builds its VariableEnvironment before any of the function's code runs. In ECMAScript 10.5, step 8:
8. For each VariableDeclaration... d in code, in source text order do
a. Let dn be the Identifier in d.
...
i. Call env’s CreateMutableBinding concrete method passing dn and configurableBindings as the arguments.
ii. Call env’s SetMutableBinding concrete method passing dn, undefined, and strict as the arguments.
This is quite a mouthful, but basically it says:
Before you run a function, look through the function's source code for declarations like var [identifierName].
For each declaration you find, create a new variable in the function's scope with the name [identifierName] used in the declaration and then set its value to undefined
It's called variable hoisting, and it's a good concept to understand as it can occasionally create bugs that are hard to track down.
For example:
var stuff = 'stuff';
function() {
console.log(stuff); //outputs 'undefined'
var stuff = 'other stuff';
console.log(stuff); //outputs 'other stuff'
}
The first console.log outputs undefined because the var stuff in the function was hoisted to the top of the function.
//theoretical compiled output
var stuff = 'stuff';
function() {
var stuff; //has not been defined
console.log(stuff);
stuff = 'other stuff'; //defined here
console.log(stuff);
}
Without knowledge of variable hoisting, this result may be confusing.
For this reason, if you look at professionally developed JavaScript code, typically you'll see all variables in a function are declared at the top.
Yes. In JavaScript, variables are hoisted
A variable statement declares variables that are created as defined in 10.5. Variables are initialised to undefined when created. A variable with an Initialiser is assigned the value of its AssignmentExpression when the VariableStatement is executed, not when the variable is created.ES5 §12.2
Where 10.5 step 8 is the part of interest
The guys answers are correct. for your example however it is worth noting that country is undefined. as aspillers has mentioned your code behaves as below
var country;
var i;
country = "USA";
switch (country) {
case "USA":
country = i;
case "blach":
//not finished yet
}
i = 10;
alert(country) //undefined;
but when your case statement ran for "USA", i was undefined so this was assigned to country. try it here in this fiddle.
I guess that you just need to be aware that although the variable declarations are hoisted, the value assignments aren't.
Yes, you can use a variable before declaring it. It's called hoisting in JavaScript.
One thing to keep in mind though is that only a variable's declaration is hoisted, not its initialization.
It means that you'll not able to use the value of the variable which you'll assign later in the code. For example,
console.log(myVar); //undefined
myVar = 10;
var myVar;
So you'll not get the error (myVar is not defined) even when you're using myVar before declaring it. But the console logged value of myVar will be undefined. At the starting of code execution, variable was declared, but its assignment was not. So the JS engine would see the above code block as
var myVar;
console.log(myVar); //undefined
myVar = 10;
var myVar;
It will put the declaration for all the variables used in the file at the top of the code.

JavaScript variable hoisting behavior [duplicate]

This question already has answers here:
Are variables declared with let or const hoisted?
(7 answers)
Closed 4 years ago.
I'm probably missing something very fundamental but I would like to ask this regardless
var a=100;
function f(){
console.log(a)
const a=150
}
console.log(a)
f();
Prints 100 and throws an error while changing const a=150 to var a=150 returns 100 and undefined. I'm unsure why this behavior occurs and any pointers to relevant info is appreciated
In general, this is how hoisting works:
the declaration of the variable is moved to the top
the variable is initialized with a special "hoisted" value
when the program reaches the var/let/const line, the variable is re-initialized with the value mentioned on that line (or undefined if there's none).
Now, your example can be simplified down to this:
console.log(a)
let a = 150
which is actually:
a = <hoisted value>
console.log(a)
a = 150
It throws an error because, for let and const, the hoisted value is a special object that raises an error when you try to access it.
On the other side, the hoisted value for var is just undefined, so this will print undefined without throwing an error:
console.log(a)
var a = 150
Also, there's some confusion (including this very thread) about which variable types are hoisted, and a so-called "dead zone" for let/const vars. It's simpler to think of things this way: everything is hoisted, that is, all variable bindings in a block are created before entering the block. The only difference between var and let/const in this regard is that with the latter you are not allowed to use a binding until you initialize it with a value.
See https://stackoverflow.com/a/31222689/989121 for more details.
const and let have temporal dead zone so when you try to access const or let before it is instantiated you get an error.
This is not true for var. var is hoisted at the top meaning it is instantiated with a value of undefined just before a function code is run.
The problem is that with new ES6, let and const, hoisting is not applied what this means is that a variable declared with either let or const cannot be accessed until after the declaration, if you do this will throw and error
var a=100;
function f(){
console.log(a)// throws an error because is accessed before is declared....
const a=150
}
console.log(a)
f();
This is commonly called the Temporal Dead Zone
On the other hand using Var will apply hoisting what this does is defines the variable in memory before all the scope is executed...
var a=100;
function f(){
console.log(a)// This won't throw an error
var a=150
}
console.log(a)
f();
the problem is
the variable with const cannot be declared more then once,
and when you declares const a=150 inside a function, it deleted the previous variable and this is why the error is coming
I think the answer your looking for is const is block scope and is not hoisted, whereas var is hoisted.
That's why you get 100, "Error: a is not defined" with:
var a=100;
function f(){
console.log(a)
const a=150
}
console.log(a)
f();
and 100, undefined with:
var a=100;
function f(){
console.log(a)
var a=150
}
console.log(a)
f();
In the second instance a is declared, but it is not defined yet. You'll see the same result with:
function f() {
console.log(a)
var a=150
}
console.log(a)
f();
Since the var inside the function is hoisted.
Bottom line: const variables are not hoisted, var variables are.

Why is this console log affected by a subsequent if statement?

Consider the following code:
var a = 'a';
function b() {
console.log(a);
if (!a) {
var a = 'b';
}
}
b();
Running b() prints undefined to the console. However, if you remove the if statement, or even simply remove the var keyword from the expression within the if statement so that you're redefining the outer a variable, the string a will be printed to the console as expected.
Can anyone explain this? The only cause I can think of is that this is a race condition, and the if statement is running just a tad faster than the console.log.
This is not a race condition - it's a language feature and is working as the designers of the Javascript language intended.
Because of hoisted variable definitions (where all variable definitions within a function scope are hoisted to the top of the function), your code is equivalent to this:
var a = 'a';
function b() {
var a;
console.log(a);
if (!a) {
a = 'b';
}
}
b();
So, the locally declared a hides the globally declared a and initially has a value of undefined until your if statement gives it a value.
You can find lots of discussion about this characteristic of the Javascript language by searching for "Javascript hoisting".
When you use var statement in a function, it will be creating a new variable which is local to that function.
All the variables declared in the function, will be moved to the top of the function, irrespective of the place where they are actually declared. This is called Hoisting.
The hoisted variables will have the value undefined, by default, till they are explicitly assigned a value.
It prints undefined as it is, because of the 3rd point.
In your case, you declared a variable a within the if block. Since the variables are hoisted, the declaration is moved to the top of the function. It has the same name as the outer variable. When you access a in the function, it first looks in the current scope if there is a variable by that name exists. It checks other scopes only if it is not found in local scope. So, the local a shadows the outer a. When you remove the var statement, there is no a in local scope, so the outer a is used. That is why it prints a.

Variables defined in global scope with identical names

Can anybody explain, why next js code rises two alert windows with 'string1' text rather than to rise the second with 'undefined' text inside?? If both variables are described in the same scope..
var a = 'string1';
alert(a);
var a;
alert(a);​
http://jsfiddle.net/FdRSZ/1/
Thanks
Variable declarations (and function declarations) are hoisted to the top of the scope in which they appear. Assignments happen in place. The code is effectively interpreted like this:
var a;
var a;
a = 'string1';
For example, consider what happens if you declare a variable inside an if statement body:
console.log(myVar); //undefined (NOT a reference error)
if (something === somethingElse) {
var myVar = 10;
}
console.log(myVar); //10
Because JavaScript does not have block scope, all declarations in each scope are hoisted to the top of that scope. If you tried to log some variable that was not declared, you would get a reference error. The above example is interpreted like this:
var myVar; //Declaration is hoisted
console.log(myVar);
if (something === somethingElse) {
myVar = 10; //Assignment still happens here
}
console.log(myVar);
So even if the condition evaluates to false, the myVar variable is still accessible. This is the main reason that JSLint will tell you to move all declarations to the top of the scope in which they appear.
In slightly more detail... this is what the ECMAScript 5 spec has to say (bold emphasis added):
For each VariableDeclaration and VariableDeclarationNoIn d in code, in
source text order do
Let dn be the Identifier in d.
Let
varAlreadyDeclared be the result of calling env’s HasBinding concrete
method passing dn as the argument.
If varAlreadyDeclared is false, then
Call env’s CreateMutableBinding concrete method passing dn and
configurableBindings as the arguments.
Call env’s SetMutableBinding concrete method passing dn, undefined, and strict as the arguments.
So, if a binding already exists with the identifier we are trying to bind now, nothing happens.
Thats because JavaScript does something called variable hoisting. In fact, your JS looks like this:
var a; // hoisted -> declared on top
a = 'string1';
alert(a);
alert(a);
See How Good C# Habits can Encourage Bad JavaScript Habits for more details on how JavaScript works.
That's because the second var a isn't a separate variable declaration. As far as the javascript interpreter is concerned it is the same a as the first one.
var means "Scope this variable to this function" not "Set the value of this variable to undefined".
If the variable is already scoped to the function then var foo means the same as just plain foo

Categories

Resources