Understanding javascript hoisting and execution context - javascript

b();
console.log(a);
var a = 'Hello World';
function b(){
console.log('Called b!');
}
I have read about the term "hoisting", but it isn't pretty clear to me. Why does the function gets executed while the variable is set to undefined?
The interesting part is, the variable didn't show any error. But it showed undefined. But when I remove the variable totally, then it shows an error. That means, the variable is present somewhere though. right?
But if it is present, then why can't the compiler compile it and can compile the function here?
I know that var a is getting hoisted. I want to know why the engine is treating the variable and the function in a different way that is what's happening behind the scenes during the execution context.
Any detailed explanation would be helpful about how the engine is creating the execution context.
In this question I'm asking about how javascript engine is behaving differently with the function and the variable. And what is exactly happening in the creating state and execution state of the execution phase. So, it's not a duplicate question.

But if it is present, then why can't the compiler compile it and can compile the function here?
Basically it boils down to whether the value of the binding can be determined without executing the code or not.
The function declaration itself doesn't depend on runtime information. Keep in mind that the body is not evaluated until the function is called. So even without really executing the code, its clear that the value of b is a function.
However, the initialization value of a variable declaration may depend on runtime information. Consider this:
var a = 10 + bar();
There is no way for the engine to "hoist" the initialization value without evaluating the expression (and executing bar in the process).
Of course in your example, the initialization value ('Hello World') is static as well, so it could be hoisted. But then the behavior would be inconsistent and probably more confusing.
What exactly happens when control enters a new function is defined in the spec. There you can see how variable declarations and function declarations are treated.

With hoisting, this is what your code looks like
function b(){
console.log('Called b!');
}
var a;
b();
console.log(a);
a = 'Hello World';
As you can see, a is declared at the the top, but has not been set to a value yet. That is why you get undefined when you log that variable.
If you remove the a variable altogether, you get the Uncaught ReferenceError because a has not been declared.

The above code is same as below
var a;
function b(){
console.log('Called b!');
}
b();
console.log(a);
a = 'Hello World';
Explanation - Function along with its definition are hoisted to the top. Variable declaration is hoisted not its definition

var a; is hoisted. a = 'Hello World!'; is not hoisted. It's that simple.

Related

Does a statement with only a variable name do something in JavaScript?

In this example:
someVariable;
does the code do anything? More technically, is there some work associated with it from the point of view of a JS engine like V8?
I'm asking because I'm looking to temporarily suppress the "variable is declared but its value is never read" warning by TypeScript and I'm doing this:
function xyz(arg) {
arg;
// ...
}
Is there a better "no-op" construct in JavaScript?
One thing it does is it checks to see if the variable is defined, If it isn't, it'll throw an error.
If you're worried about side-effects, if you happen to be inside a with statement, it can invoke a getter and run code, but this is unlikely. If the variable name in question isn't local and happens to be a getter on window, it can also run code, eg
Object.defineProperty(window, 'foo', { get() {
console.log('getting');
}});
console.log('start');
foo;
But this, too, is pretty unlikely.
If you're sure the variable referred to is a normal variable in scope, it won't do anything - it'll just be an unused expression.
Beside the checking of the exisiting of the variable, it perfoms an evaluation of the expression.
var foo = {
get bar() {
console.log('get bar');
return 42;
}
};
foo.bar;

Function declarations precedence/overwriting variable declarations? Hoisting? Why?

Snippet 1:
var a; // undefined variable named 'a'
function a(foo) { // a function named 'a'
var foo = "Hello World";
console.log(foo);
}
console.log(a); // output is: [Function: a], but why not undefined?
Snippet 2:
function a(foo) { // a function named 'a'
var foo = "Hello World";
console.log(foo);
}
var a; // undefined variable named 'a'
console.log(a); // output is: [Function: a], but why not undefined?
I could have just shown Snippet 1 to ask this question - however I showed both just for completeness purposes. I have wrote some brief comments in them as well.
My question is, in both cases, why is the function declaration ‘overwriting’/’shadowing’ or taking ‘precedence’ over the variable declaration? Can someone please explain this behaviour?
I understand that these arguably are the same (from the perspective of the interpreter) in terms of end-result, due to the ‘hoisting’ phenomenon, but why does the function declaration or the variable declaration have precedence over the other when it’s interpreted/parsed by the Javascript engine (during the creation phase)? i.e. which one gets hoisted above the other? I have read it is that the function declaration has precedence over the variable declaration - but why is this the case?
Also, kindly refer to the first code snippet (but this applies to both cases), is the memory location/address of ‘a’ where it’s declared in line 1, and line 6, EXACTLY the same? And since ‘a’, in both places of the code, represents the function declaration, what would be the value of ‘a’ at its memory location/address after parsing line 1 and line 6 during the creation phase? Since function declarations are 'hoisted' above the variable declaration, does that mean that by line 1, 'a's memory address is pointing to the function object 'a', by the end of the creation phase of the execution context?
In both code snippets, ‘var a’ is undefined, so why isn’t ‘a’ the value of undefined by the time we reach the execution phase (which has its execution point starting on line 6?) Does the Javascript engine simply say, “Ah, if we allow ‘var a’ to ‘overwrite’ ‘function a() {…}’, it would continue to be undefined and thus be unusable. Whereas, if we allow ‘a’ to represent said function, then at least the user can invoke said function (even prior to its declaration, without getting a reference error)". This is very unlikely to be the case but sounds logical/ideal, maybe?
So, my questions are:
What’s the reason behind why the function declaration is overwriting or having precedence over the variable declaration? Is it something we just accept prima-facie because it's an implementation of the ECMAScript specifications or can we explain this behaviour?
And
If possible, could someone please answer what is happening in memory when this occurs every step of the way?
I have been trying to use my intuition for the last 8 hours (where I ended up spiraling into another dimension of the other peculiarities of JavaScript, but that’s another issue in itself) but I would to know if there is a simple or concrete explanation or answer to this behaviour.
Any help in understanding all of this would be much appreciated.
My question is, in both cases, why is the function declaration ‘overwriting’/’shadowing’ or taking ‘precedence’ over the variable declaration? Can someone please explain this behaviour?
There is only one place in either snippet where the variable a is given a value, and that's the function declaration. The statement var a; means "I announce that a variable named a exists". Since the function declaration is taking care of announcing that it exists and giving it a value, the var a; statement doesn't really have any effect.
In fact, if we refer to Section 10.5.8 of the JavaScript spec, we can see that the end result of this var a; is literally to do nothing because the a variable is already declared by the time the var a; declaration is processed.
I understand that these arguably are the same (from the perspective of the interpreter) in terms of end-result, due to the ‘hoisting’ phenomenon, but why does the function declaration or the variable declaration have precedence over the other when it’s interpreted/parsed by the Javascript engine during the creation phase?
Nothing is taking "precedence" here. There is only one variable named a. var a; does not give a a value, so it has no effect on a's value.
Also, kindly refer to the first code snippet (but this applies to both cases), is the memory location/address of ‘a’ where it’s declared in line 1, and line 6, EXACTLY the same?
There is only one a variable and it only takes on one value, so this question is mostly nonsensical, but in rough terms, the a variable itself would only exist in one place and it would only refer to one value (memory location), which would be the definition of that function.
Since function declarations are 'hoisted' above the variable declaration, does that mean that by line 1, 'a's memory address is pointing to the function object 'a', by the end of the creation phase of the execution context?
My knowledge of the creation phase isn't that great, but in the course of this code's execution, a only ever refers to one value, as I said above.
In both code snippets, ‘var a’ is undefined, so why isn’t ‘a’ the value of undefined by the time we reach the execution phase (which has its execution point starting on line 6?)
See my first and second answers.
What’s the reason behind why the function declaration is overwriting or having precedence over the variable declaration? And
As I've said, it's not taking "precedence", but the reason JavaScript has function hoisting is in order to allow people to call functions from a line in the code before the function's actual definition, similar to how other major languages like C# and Java do.
If possible, could someone please answer what is happening in memory when this occurs every step of the way?
The JavaScript spec doesn't define what happens in memory. It defines the code's external behavior. So this would be an implementation detail and would be engine-specific.
Here is a rough blow by blow of what happens when your code is executed (in both cases):
Create a variable called a and assign it the value of that function you have there.
Check whether there is a variable called a. There already is one, so do nothing.
Execute console.log and pass it the value of a (which is that function)
The function declaration gets hoisted before the variable hoisting.
console.log(a);
var a = 42; // assignment
console.log(a);
function a(foo) { // a function named 'a'
var foo = "Hello World";
console.log(foo);
}
console.log(a);

What's the difference between "LexicalEnvironment" and "VariableEnvironment" in spec

I'm reading the ECMAScript 2015 specification, and the terms "LexicalEnvironment" and "VariableEnvironment" are used many times. They are defined in table 23:
LexicalEnvironment: Identifies the Lexical Environment used to resolve identifier references made by code within this execution context.
VariableEnvironment: Identifies the Lexical Environment whose EnvironmentRecord holds bindings created by VariableStatements within this execution context.
The LexicalEnvironment and VariableEnvironment components of an execution context are always Lexical Environments. When an execution context is created its LexicalEnvironment and VariableEnvironment components initially have the same value.
So, I want to know how they will be different, and which situations each are used in. Could anyone explain?
I post the question to offical ECMA262 organization on github, this is the answer of littledan:
A LexicalEnvironment is a local lexical scope, e.g., for let-defined variables. If you define a variable with let in a catch block, it is only visible within the catch block, and to implement that in the spec, we use a LexicalEnvironment. VariableEnvironment is the scope for things like var-defined variables. vars can be thought of as "hoisting" to the top of the function. To implement this in the spec, we give functions a new VariableEnvironment, but say that blocks inherit the enclosing VariableEnvironment.
This is a hard one. I will try to explain with some simple examples. So one important thing, in this question is also to understand the execution context.
Lexical Environment
Means where you write something in the code is important. Not all programming languages are like that, but javascript is.
So if you have a function like
function hello() {
var myVar = 'hello';
}
Now the variable myVar sits lexically inside the function. That's physically the code that you're writing.
In short, if talking about lexical environment means where it is written and what surrounds it.
Variable Environment
Every time you call a function a new execution context will be created. So even myVar is declared 3 times (see next example) they do not touch each other. That's when you talk about Variable Environment
function b() {
var myVar;
console.log('three', myVar) // three undefined
// cause myVar is newly declared in b()
// but has no value
}
function a() {
var myVar = 2;
console.log('two', myVar) // two 2
b();
}
var myVar = 1;
console.log('one', myVar) // one 1
a();
console.log('four', myVar) // one 1
Now you where asking for the difference which I guess it is just the theoretical talk about two things. But also the lexical environment kinda knows where the variables are sitting in memory.
So that is actually the answer to your question. But I will show some more examples just to make sure where things can go wrong with misunderstanding.
Because there is also this thing called hoisting in javascript which can give you errors if you write code at the wrong place. And it can have strange behaviour. The next examples are actually very simple but all depend on Lexical Environemnt, Variable Environment, Execution Context and hoisting
console.log(myVar); // undefined
var myVar = 'hello';
console.log(myVar); // hello
but
function a() {
console.log(myVar) // gives Error myVar is not defined
}
a();
but again:
function a() {
console.log(myVar); // undefined no Error
// cause it would take myVar from global
// execution context
// but also no error cause we define it again
// in this function (hoisting)
var myVar = 0; // define myVar newly in this lexical environment
console.log(myVar); // 0
}
var myVar = 'hello';
a();
console.log(myVar); // hello
But again if we do like so
function a() {
myVar = 0; // overwrite global myVar
console.log(myVar); // 0
}
var myVar = 'hello';
a();
console.log(myVar); // 0 did you expect myVar to be 0 ?

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