Variable not hoisted - javascript

In Javascript variables are hoisted to the top of the scope they are declared within.
However in the following code it seems that the variable myvar is not hoisted.
<html>
<body>
</body>
</html>
<script type="text/javascript">
console.log(typeof myvar);
var myvar = "value";
console.log(typeof myvar);
</script>
The output of the above is:
undefined
string
I expected that the first line would say "string" because myvar is supposed to be hoisted to above it.
Why isn't this so?

Variable declarations are hoisted, the assignments are not.
By using var myvar anywhere in the function you create a locally scoped variable myvar, but if you follow it with = something then the assignment will take place in normal code order.

A dupe of this came up, and Quentin's answer is good (as always), but just to spell it out even more:
The way the JavaScript engine actually processes that code is like this:
// Before any step-by-step code
var myvar;
// Now step-by-step starts
console.log(typeof myvar); // undefined since no value has been written to it
myvar = "value";
console.log(typeof myvar); // "value" because that's its value now
That is, this:
var myvar = "value";
... is actually two separate things that happen at two separate times. The variable declaration (the var myvar part), which happens before any step-by-step code in the scope is run, and the initialization (the myvar = "value" part; it's really an assignment expression by the time it's processed), which happens where that line is in the code.

Related

Javascript Function Scope Confusion

Can someone explain this to me:
var test = 5;
// prints 5;
function printMe1(){
console.log(test);
}
// prints "undefined"
function printMe2(){
console.log(test);
var test = 10;
}
Is this because printMe2 creates a local variable of "test"? And if so, why does the log statement refer to the local variable, if it is declared after it?
And also, if JS is an interpreted language, shouldn't the code be interpreted line by line? In which case the log statement shouldn't be able to know that the local "test" variable is declared later?
there is a concept in javascript "hoisting" so in hoisting variables and function declarations are moved to the top of their scope before code execution. remember only declaration, not the definition. that's why in your code var test is showing undefined because you are using this variable before defining it.
var test;
function printme2(){
console.log(test)
test=10
}
printme2()
I just did some googling and found the answer.
It is because Javascript "hoists" variable declarations to the top of the scope. So the local "test" variable was declared at the top of the function scope, thus the reason why printing it gave "undefined".
(if any of this wrong let me know please :) )

javaScript hoisting not working properly

These are 2 examples which must have attained same result:
Example 1
<script>
console.log(a);
var a = 10;
console.log(a);
</script>
Rendered
<script>
var a = "";
console.log(a); //will result undefined
a = 10;
console.log(a); //will result 10
</script>
Result
undefined
10
Example 2
<script>
console.log(a);
a = 10;
console.log(a);
</script>
Expectation of Rendering
<script>
var a = "";
console.log(a); //should result undefined
a = 10;
console.log(a); //should result 10
</script>
Result
Now, as per JS Hoisting in Scenario 2, the variable if not declared must have been automatically declared onto top of its scope and still result should have been the same. Why is it not? Where is the concept failed?
The second case is different, because
a = 10
... does not declare a hoisted variable. It creates a property in the window object (even if the code would have been inside a function). This is not a declaration, and thus something that is not hoisted. So before you create that property, it does not exist.
Note that what you listed as rendered code is not entirely correct. A hoisted variable does not get a value, so for your first example it should look like this:
var a; // undefined!
console.log(a); // will output undefined
a = 10;
console.log(a); // will output 10
Note that if this code is not part of a function body, var a also creates the window.a property, and this happens at the hoisted declaration.
And for your second example, the rendered code could look like this
console.log(a); // Error: does not exist.
window.a = 10;
console.log(a); // will output 10
JavaScript hoists declarations, not initializations, see this page.
If you add a 'var a;' somewhere in your second example, it should work fine!
On example 2, at the time you run the first console log, a is really undefined.
a = 10 sets a new property a to the window object and there's no 'hoisting' when setting a property to an object that already exists.
when we will execute a source code .IN hoisting, The declaration variable goes over console.log().Then the variable allowcated a memory but does not access it. When I declaration a variable in memory. Then we give by default undefined value in place of that variable. (as like ,in html,place Holder works like this.
--- So you have not declared any variable. Hosting will not work here.
--- Can't access a here..Because when you define a variable.
Then you must be defined a variable.here u can not make variable so output: cannot access a

JavaScript variable hoisting example

I have a question on variable hoisting in JavaScript.
Consider the following example:
​
var myName = "Richard"; // Variable assignment (initialization)
​
​function myName () {
console.log ("Rich");
}
​
console.log(typeof myName); // string
I am actually confused why typeof myName is returned as string.
As per my understanding, the example would be proceessed as below;
First the function declaration (function myName ()) would get hoisted to the top and then
JS interpreter would read the line var myName = "Richard" (since function declaration gets precedence over variable declaration). However, since there would already be a property with the name "myName", this statement would get ignored.
Thus typeof myName should get returned as function (and not string).
Where is my understanding incorrect?
JavaScript has a dynamic type system, i.e. the type of variables can change over time. Basically, what you write is correct: First, the function declaration gets run (on loading the file), but then the function stored in the variable myName is being overwritten by the string.
The only thing that gets ignored is the call to var, as the variable is actually already declared.
But it is perfectly valid to re-define a variable (and that's what you do here, by assigning a new value).
In the end, your sample is nothing but this:
var x = 23;
x = 'foo';
This will work as well, x will be 'foo', and its type is going to be string. The only difference to your sample is that in yours, a value of type function is involved.
In addition to the other answers what should be noted is that, if you declare your function in the following manner:
var myName = function() {
console.log('Rich');
}
or simply
myName = function(){
console.log('Rich')
}
as opposed to the "function myName . . . " syntax, then typeof myName will return "function"
2 years passed, but perhaps it's still relevant to someone
You are correct, when interpreting an object this is indeed so:
Scan the context for function declarations
For each function found, create a property in the variable object
If the function name exists already, the reference pointer value will be overwritten
Scan the context for variable declarations
For each variable declaration found, create a property in the variable object that is the variable name, and initialize the value as undefined
If the variable name already exists in the variable object, do nothing and continue scanning
However it looks like this is isn't so for global scope.
I.e. when I define an object the output is exactly as it should be, when I define the same in the global scope it's not....
Still trying to wrap my head around this one
The idea of "hoisting" is a bad way to understand what's going on. In other words, in my opinion "hoisting" is a bad explanation for hoisting.
What's really going on is not "hoisting". What's really going on is that javascript executes code in two phases: the compile phase and the eval phase. The javascript community calls the symptom of this "hoisting" but most people fail to understand why hoisting hoists because they think javascript interpreters have this feature called "hoisting" (they don't).
What actually happens is simpler to explain than the idea of hoisting. The rules are:
Javascript always parse code from the top-down. It never reorders code (it never hoists).
There are two phases of execution: compilation and evaluation.
All declarations are processed in the compilation phase, no expressions will be evaluated in the compilation phase (because "evaluating" things are done in the evaluation phase).
All expressions and anything else that need to be evaluated are processed in the evaluation phase.
Remember rule 1, all parsing are done top-down and there are no backtracking, no hoisting.
Let's take your example and try to understand it by keeping in mind javascript's compilation and evaluation phase:
var myName = "Richard"; // Variable assignment (initialization)
​
​ function myName () {
console.log ("Rich");
}
​ console.log(typeof myName); // string
In the compilation phase, the interpreter sees you declaring a variable. It allocates an area of memory for this variable and assigns it the value of undefined.
In the compliation phase, the interpreter sees you declaring a function. It also notices that the function name shadows the variable name. So it creates a function "myName" (which means that at this point the variable myName points to the function).
Compilation phase ends. Now we enter the evaluation phase.
In the evaluation phase, the interpreter sees you assigning a string to myName.
There is nothing to evaluate when we reach the function declaration because declarations are processed in the compilation phase.
In the evaluation phase, the interpreter sees you console.logging the typeof myName. Since the last thing assigned to it was a string it prints "string".
Note that if you remove the string assignment then myName will be typeof "function". That's because in that case the last thing assigned to it is the declared function.
See this related question for other subtleties caused by the two phases of execution: JavaScript function declaration and evaluation order
Because of Hoisting your variables and functions definitions are moved to the top, so you have:
var myName;
// moved to top
function myName () {
console.log ("Rich");
}
// next your code
myName = "Richard";
console.log(typeof myName); // string
If you rewrite your code like this:
var myName = "Richard"; // Variable assignment (initialization)
​
myName = ​function () { // Variable redefinition
console.log ("Rich");
}
​
console.log(typeof myName); // function
Your myName variable now is a function, because only the myName variable is hoisted:
var myName;
myName = "Richard"; // Variable assignment (initialization)
myName = ​function () { // Variable redefinition
console.log ("Rich");
}
​
console.log(typeof myName); // outputs 'function'

Javascript Odd Scoping Behavior

I've been going through Javascript function scope and have run into this:
var scope = "global";
function f(){
console.log(scope);
var scope = "local";
console.log(scope);
}
f();
Now I understand that the output of the first log is "undefined" because of how js hoists variables at the top of the function. BUT when I remove var from "var scope = "local";" the first log outputs "global" and this has got me scratching my head. Can someone explain why that is happening please? I mean doesn't js sequentially run the code? As such how can removing VAR have any impact on the first log?
Two-pass parsing. The code will be treated as if it was
function f() {
var scope; // var created, but no value assigned. this overrides the earlier global
console.log(scope);
scope = 'local';
console.log(scope);
}
The var's CREATION will be executed as if it was the very first bit of code executed in the function. But the actual assignment operation won't occur until where it normally would.
Javascript sometimes behaves a bit differently from other languages. Take a look at http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html, they explain it a bit.
If you omit the var statement, the first log uses the global variable, which is set with the string "global". There is no other local variable and no hoisting.
First log: global variable scope set with "global" content
Assignment of new string for the same global variable
Second log: global variable scope set with "local" content

Why does shadowed variable evaluate to undefined when defined in outside scope?

Consider the following piece of code:
<html><head></head>
<body>
<script type="text/javascript">
var outside_scope = "outside scope";
function f1() {
alert(outside_scope) ;
}
f1();
</script>
</body>
</html>
The output for this code is that the alert box displays the message "outside
scope". But, if I slightly modify the code as:
<html><head></head>
<body>
<script type="text/javascript">
var outside_scope = "outside scope";
function f1() {
alert(outside_scope) ;
var outside_scope = "inside scope";
}
f1();
</script>
</body>
</html>
the alert box displays the message "undefined". I could have
understood the logic if it displays "undefined" in both the cases. But, that
is not happening. It displays "undefined" only in the second case. Why is this?
Thanks in advance for your help!
Variables are subject to hoisting. This means that regardless of where a variable is placed within a function, it is moved to the top of the scope in which it is defined.
For example:
var outside_scope = "outside scope";
function f1() {
alert(outside_scope) ;
var outside_scope = "inside scope";
}
f1();
Gets interpreted into:
var outside_scope = "outside scope";
function f1() {
var outside_scope; // is undefined
alert(outside_scope) ;
outside_scope = "inside scope";
}
f1();
Because of that, and the function only scope that JavaScript has, is recommended to declare all the variables at the top of the function, to resemble what will happen.
In the first case, your code is accessing the global variable "outside_scope", which has been initialized to "outside scope".
Javascript has function level scope, so in the second case it is accessing the function scoped variable "outside_scope", but it has not yet been initialized at the time of the alert box. So it displays undefined.
JavaScript has function scope, not block scope.
In the second case, the declaration of outside_scope is hoisted up to the top of the function (but the assignment isn't).
This is a great example of why JavaScript code is easier to read if you put all your variable declarations up at the top of the function. Your second example is equivalent to:
function f1() {
var outside_scope;
alert(outside_scope);
outside_scope = "inside scope";
}
and you can probably now understand why you're getting "undefined."
In the second example the local variable exists for the entire function scope. It doesn't matter that you defined it after the alert, it exists for the entire function.
However, the actual assignment doesn't occur until after the alert, hence the "undefined".
This is due to something called the hoisting of variable declarations.
Basically, JavaScript separates a variable declaration in two, leaving the assignment where you did the declaration and hoisting the actual declaration to the top of the function:
var f1 = function () {
// some code
var counter = 0;
// some more code
}
var f2 = function () {
var counter; // initialized with undefined
// some code
counter = 0;
// some more code
}
On run-time, f1() gets translated into f2(). I wrote an in depth blog post about this here. I hope this helps you understand what happens in your code.
This is also the reason, it is recommended to declare your variables at the top of a function in JavaScript. It helps you understand what the code does, when it runs.
that's an interesting case.
in the first example, you have defined a 'global' variable. it has global scope and is therefore accessible in any function/object for the execution.
in the second example, you have 'blocked' the global variable with the function scope variable, but since it hasn't been initialised yet at the time of the alert, it returns 'undefined'.
i agree this isn't the most intuitive quirk, but it does make sense.

Categories