Related
I just read a great article about JavaScript Scoping and Hoisting by Ben Cherry in which he gives the following example:
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
Using the code above, the browser will alert "1".
I'm still unsure why it returns "1". Some of the things he says come to mind like:
All the function declarations are hoisted to the top. You can scope a variable using function. Still doesn't click for me.
Function hoisting means that functions are moved to the top of their scope. That is,
function b() {
a = 10;
return;
function a() {}
}
will be rewritten by the interpeter to this
function b() {
function a() {}
a = 10;
return;
}
Weird, eh?
Also, in this instance,
function a() {}
behaved the same as
var a = function () {};
So, in essence, this is what the code is doing:
var a = 1; //defines "a" in global scope
function b() {
var a = function () {}; //defines "a" in local scope
a = 10; //overwrites local variable "a"
return;
}
b();
alert(a); //alerts global variable "a"
What you have to remember is that it parses the whole function and resolves all the variables declarations before executing it. So....
function a() {}
really becomes
var a = function () {}
var a forces it into a local scope, and variable scope is through the entire function, so the global a variable is still 1 because you have declared a into a local scope by making it a function.
The function a is hoisted inside function b:
var a = 1;
function b() {
function a() {}
a = 10;
return;
}
b();
alert(a);
which is almost like using var:
var a = 1;
function b() {
var a = function () {};
a = 10;
return;
}
b();
alert(a);
The function is declared locally, and setting a only happens in the local scope, not the global var.
function declaration function a(){} is hoisted first and it behaves like var a = function () {};, hence in local scope a is created.
If you have two variable with same name (one in global another in local), local variable always get precedence over global variable.
When you set a=10, you are setting the local variable a , not the global one.
Hence, the value of global variable remain same and you get, alerted 1
Suprisingly, none of the answers here mention the relevancy of the Execution Context in the Scope Chain.
The JavaScript Engine wraps the currently executing code in an Execution Context. The base execution context is the global Execution Context. Each time a new function is invoked, a new Execution Context is created and put on the Execution Stack. Think of a Stack Frame sitting on an Invocation Stack in other programming languages. Last in first out. Now each Execution Context has its own Variable Environment and Outer Environment in JavaScript.
I will use the below example as a demonstration.
1) First, we enter the Creation Phase of the global Execution Context. Both the Outer Environment and Variable Environment of the Lexical Environment are created. The Global Object is setup and placed in memory with the special variable 'this' pointing to it. The function a and its code and the variable myVar with an undefined value are placed in memory in the global Variable Environment. it's important to note that function a's code is not executed. It is just placed in memory with function a.
2) Second, it is the Execution Phase of the Execution Context. myVar is no longer an undefined value. It is initialized with value of 1, which is stored in the global Variable Environment. The function a is invoked and a new Execution Context is created.
3) In the function a's Execution Context, it goes through the Creation and Execution Phase of its own Execution Context. It has its own Outer Environment and Variable Environment, thus, its own Lexical Environment. The function b and the variable myVar are stored in its Variable Environment. This Variable Environment is distinct from the global Variable Environment. Since the function a sits lexically (physically in code) on the same level as the global Execution Context, its Outer Environment is the global Execution Context. Thus, if the function a was to refer to a variable that is not in its Variable Environment, it will search the Scope Chain and try to find the variable in the Variable Environment of the global Execution Context.
4) The function b is invoked in function a. A new Execution Context is created. Since it sits lexically in function a, its Outer Environment is a. So when it references myVar, since myVar is not in function b's Variable Environment, it will look in function a's Variable Environment. It finds it there and console.log prints 2. But if the variable was not in function a's Variable Environment, then since function a's Outer Environment is the global Execution Context, then the Scope Chain will continue searching there.
5) After function b and a are finished execution, they are popped from the Execution Stack. The single-threaded JavaScript Engine continues execution at the global Execution Context. It invokes the b function. But there is no b function in the global Variable Environment and there is no other Outer Environment to search in the global Execution Context. Thus an exception is raised by the JavaScript Engine.
function a(){
function b(){
console.log(myVar);
}
var myVar = 2;
b();
}
var myVar = 1;
a();
b();
> 2
> Uncaught ReferenceError: b is not defined
The below example shows the Scope Chain in action. In the function b's Execution Context's Variable Environment, there is no myVar. So it searches its Outer Environment, which is the function a. The function a does not have myVar in its Variable Environment either. So the Engine searches function a's Outer Environment, which is the global Execution Context's Outer Environment and myVar is defined there. Hence, the console.log prints 1.
function a(){
function b(){
console.log(myVar);
}
b();
}
var myVar = 1;
a();
> 1
Regarding Execution Context and the Lexical Environment associated with it, including Outer Environment and Variable Environment, enable the scoping of variables in JavaScript. Even if you invoke the same function multiple times, for each invocation, it will create its own Execution Context. So each Execution Context will have its own copy of the variables in its Variable Environment. There is no sharing of variables.
function a() { } is a function statement, which creates an a variable local to the b function.
Variables are created when a function is parsed, regardless of whether the var or function statement gets executed.
a = 10 sets this local variable.
What is the bone of contention in this small snippet of code?
Case 1:
Include function a(){} definition inside the body of function b as follows. logs value of a = 1
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
console.log(a); // logs a = 1
Case 2
Exclude function a(){} definition inside the body of function b as follows. logs value of a = 10
var a = 1;
function b() {
a = 10; // overwrites the value of global 'var a'
return;
}
b();
console.log(a); // logs a = 10
Observation will help you realise that statement console.log(a) logs the following values.
Case 1 : a = 1
Case 2 : a = 10
Posits
var a has been defined and declared lexically in the global scope.
a=10 This statement is reassigning value to 10, it lexically sits inside the function b.
Explanation of both the cases
Because of function definition with name property a is same as the variable a. The variable a inside the function body b becomes a local variable. The previous line implies that the global value of a remains intact and the local value of a is updated to 10.
So, what we intend to say is that the code below
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
console.log(a); // logs a = 1
It is interpreted by the JS interpreter as follows.
var a = 1;
function b() {
function a() {}
a = 10;
return;
}
b();
console.log(a); // logs a = 1
However, when we remove the function a(){} definition, the value of 'a' declared and defined outside the function b, that value gets overwritten and it changes to 10 in case 2. The value gets overwritten because a=10 refers to the global declaration and if it were to be declared locally we must have written var a = 10;.
var a = 1;
function b() {
var a = 10; // here var a is declared and defined locally because it uses a var keyword.
return;
}
b();
console.log(a); // logs a = 1
We can clarify our doubt further by changing the name property in function a(){} definition to some other name than 'a'
var a = 1;
function b() {
a = 10; // here var a is declared and defined locally because it uses a var keyword.
return;
function foo() {}
}
b();
console.log(a); // logs a = 1
Hoisting is a concept made for us to make it easier to understand. What actually happens is the declarations are done first with respect to their scopes and the assignments will happen after that(not at the same time).
When the declarations happen, var a, then function b and inside that b scope, function a is declared.
This function a will shadow the variable a coming from the global scope.
After the declarations are done, the values assign will start, the global a will get the value 1 and the a inside function b will get 10.
when you do alert(a), it will call the actual global scope variable.
This little change to the code will make it more clear
var a = 1;
function b() {
a = 10;
return a;
function a() { }
}
alert(b());
alert(a);
It is happening because of the Variable name is same as the function name means "a".
Thus due to Javascript hoisting it try to solve the naming conflict and it will return a = 1.
I was also confused about this until i read this post on "JavaScript Hoisting" http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html
Hope it helps.
Here's my recap of the answer with more annotation and an acompaniying fiddle to play around with.
// hoisting_example.js
// top of scope ie. global var a = 1
var a = 1;
// new scope due to js' functional (not block) level scope
function b() {
a = 10; // if the function 'a' didn't exist in this scope, global a = 10
return; // the return illustrates that function 'a' is hoisted to top
function a(){}; // 'a' will be hoisted to top as var a = function(){};
}
// exec 'b' and you would expect to see a = 10 in subsequent alert
// but the interpreter acutally 'hoisted' the function 'a' within 'b'
// and in doing so, created a new named variable 'a'
// which is a function within b's scope
b();
// a will alert 1, see comment above
alert(a);
https://jsfiddle.net/adjavaherian/fffpxjx7/
scpope & closure & hoisting (var/function)
scpope : the global var can be access in any place(the whole file
scope), local var only can be accessed by the local
scope(function/block scope)!
Note: if a local variable not using
var keywords in a function, it will become a global variable!
closure : a function inner the other function, which can access
local scope(parent function) & global scope, howerver it's vars
can't be accessed by others! unless, your return it as return value!
hoisting : move all declare/undeclare vars/function to the scope
top, than assign the value or null!
Note: it just move the declare,not move the value!
var a = 1;
//"a" is global scope
function b() {
var a = function () {};
//"a" is local scope
var x = 12;
//"x" is local scope
a = 10;
//global variable "a" was overwrited by the local variable "a"
console.log("local a =" + a);
return console.log("local x = " + x);
}
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x =
console.log(x);
// ReferenceError: x is not defined
Hoisting In JavaScript means, variable declarations are executed through out the program before any code is executed. Therefore declaring a variable anywhere in the code is equivalent to declaring it at the beginning.
Its all depends on the scope of variable 'a'. Let me explain by creating scopes as images.
Here JavaScript will create 3 scopes.
i) Global scope.
ii) Function b() scope.
iii) Function a() scope.
Its clear when you call 'alert' method scope belongs to Global that time, so it will pick value of variable 'a' from Global scope only that is 1.
Long Post!
But it will clear the air!
The way Java Script works is that it involves a two step process:
Compilation(so to speak) - This step registers variables and function declarations and their respective scope. It does not involve evaluating function expression: var a = function(){} or variable expression (like assigning 3 to x in case of var x =3; which is nothing but the evaluation of R.H.S part.)
Interpreter: This is the execution/evaluation part.
Check the output of below code to get an understanding:
//b() can be called here!
//c() cannot be called.
console.log("a is " + a);
console.log("b is " + b);
console.log("c is " + c);
var a = 1;
console.log("Now, a is " + a);
var c = function() {};
console.log("Now c is " + c);
function b() {
//cannot write the below line:
//console.log(e);
//since e is not declared.
e = 10; //Java script interpreter after traversing from this function scope chain to global scope, is unable to find this variable and eventually initialises it with value 10 in global scope.
console.log("e is " + e) // works!
console.log("f is " + f);
var f = 7;
console.log("Now f is " + f);
console.log("d is " + d);
return;
function d() {}
}
b();
console.log(a);
Lets break it:
In the compilation phase,
'a' would be registered under global scope with value 'undefined'.
Same goes for 'c', its value at this moment would be 'undefined' and not the 'function()'.
'b' would be registered as a function in the global scope.
Inside b's scope, 'f' would be registered as a variable which would be undefined at this moment and function 'd' would be registered.
When interpreter runs, declared variables and function() (and not expressions) can be accessed before the interpreter reaches the actual expression line. So, variables would be printed 'undefined' and declared anonymous function can be called earlier. However, trying to access undeclared variable before its expression initialisation would result in an error like:
console.log(e)
e = 3;
Now, what happens when you have variable and function declaration with same name.
Answer is - functions are always hoisted before and if the same name variable is declared, it is treated as duplicate and ignored. Remember, order does not matter. Functions are always given precedence. But during evaluation phase you can change the variable reference to anything (It stores whatever was the last assignment) Have a look at the below code:
var a = 1;
console.log("a is " + a);
function b() {
console.log("a inside the function b is " + a); //interpreter finds 'a' as function() in current scope. No need to go outside the scope to find 'a'.
a = 3; //a changed
console.log("Now a is " + a);
return;
function a() {}
}
var a; //treated as duplicate and ignored.
b();
console.log("a is still " + a + " in global scope"); //This is global scope a.
Hoisting is behavioural concept of JavaScript. Hoisting (say moving) is concept that explains how and where variables should be declared.
In JavaScript, a variable can be declared after it has been used because Function declarations and variable declarations are always moved (“hoisted”) invisibly to the top of their containing scope by the JavaScript interpreter.
We encounter two types of hoisting in most cases.
1.Variable declaration hoisting
Lets understand this by this piece of code.
a = 5; // Assign 5 to a
elem = document.getElementById("demo"); // Find an element
elem.innerHTML = a; // Display a in the element
var a; // Declare a
//output-> 5
Here declaration of variable a will be hosted to top invisibly by the javascript interpreter at the time of compilation. So we were able to get value of a. But this approach of declaration of variables is not recommended as we should declare variables to top already like this.
var a = 5; // Assign and declare 5 to a
elem = document.getElementById("demo"); // Find an element
elem.innerHTML = a; // Display a in the element
// output -> 5
consider another example.
function foo() {
console.log(x)
var x = 1;
}
is actually interpreted like this:
function foo() {
var x;
console.log(x)
x = 1;
}
In this case x will be undefined
It does not matter if the code has executed which contains the declaration of variable. Consider this example.
function foo() {
if (false) {
var a = 1;
}
return;
var b = 1;
}
This function turns out to be like this.
function foo() {
var a, b;
if (false) {
a = 1;
}
return;
b = 1;
}
In variable declaration only variable definition hoists, not the assignment.
Function declaration hoisting
Unlike the variable hoisting the function body or assigned value will also be hoisted. Consider this code
function demo() {
foo(); // this will give error because it is variable hoisting
bar(); // "this will run!" as it is function hoisting
var foo = function () {
alert("this would not run!!");
}
function bar() {
alert("this will run!!");
}
}
demo();
Now as we understood both variable and function hoisting, let's understand this code now.
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
This code will turn out to be like this.
var a = 1; //defines "a" in global scope
function b() {
var a = function () {}; //defines "a" in local scope
a = 10; //overwrites local variable "a"
return;
}
b();
alert(a);
The function a() will have local scope inside b(). a() will be moved to top while interpreting the code with its definition (only in case of function hoisting) so a now will have local scope and therefore will not affect the global scope of a while having its own scope inside function b().
From my piece of knowledge, hoisting happens with the variable declaration and function declaration, for example:
a = 7;
var a;
console.log(a)
What happens inside JavaScript's engine:
var a;
a = 7;
console.log(a);
// 7
Or:
console.log(square(7)); // Output: 49
function square(n) { return n * n; }
It will become:
function square(n) { return n * n; }
console.log(square(7)); // 49
But assignments such as variable assigment, function expression assignment will not be hoisted:
For example:
console.log(x);
var x = 7; // undefined
It may become like this:
var x;
console.log(x); // undefined
x = 7;
To describe hosting in javascript in one sentence is variables and functions are hoisted to the top of the scope that they are declared in.
I am assuming you are a beginner, to understand hoisting properly at first we have understood the difference between undefined and ReferenceError
var v;
console.log(v);
console.log(abc);
/*
The output of the above codes are:
undefined
ReferenceError: abc is not defined*/
now in the bellow code what we see? a variable and a function expression is decleard.
<script>
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
</script>
but the real picture with proof that the both variable and function are hoisted on the top of there scope:
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));
Output of first two logs are undefined and TypeError: getSum is not a function because both var totalAmo and getSum are hoisted on the top of their scope like bellow
<script>
var totalAmo;
var getSum;
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));
</script>
But for functions declaration whole functions hoisted on the top of their scope.
console.log(getId());
function getId(){
return 739373;
}
/* output: 739373, because the whole function hoisted on the top of the scope.*/
Now the same logic goes for those varibale, functions experessions and function declaratoins declared inside functional scope. Key point: they will not be hoisted on the top of the file;
function functionScope(){
var totalAmo;
var getSum;
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
}
So, when you use var keyword, variable and function hoisted on the top of there scope (global scope and function scope).
What about let and const, const and let are still both aware of the global scope and function scope just like var is, but const and let variables are also aware of another scope called blocked scope. a block scope is present whenever there is a block of code, such as for loop, if else statement, while loop etc.
When we use const and let to declare a variable in these block scope, the variable declaration only will be hoisted on the top of that block that it is in, and it will not be hoisted on the top of the parent function or top of the global scope that it is hoisted.
function getTotal(){
let total=0;
for(var i = 0; i<10; i++){
let valueToAdd = i;
var multiplier = 2;
total += valueToAdd*multiplier;
}
return total;
}
Variables in abobe example will be hoisted like bellow
function getTotal(){
let total;
var multiplier;
total = 0;
for(var i = 0; i<10; i++){
let valueToAdd;
valueToAdd = i;
multiplier = 2;
total += valueToAdd*multiplier;
}
return total;
}
ES5: function hoisting & variable hoisting
function hoisting priority is greater than variable hoisting
"use strict";
/**
*
* #author xgqfrms
* #license MIT
* #copyright xgqfrms
* #created 2016-06-01
* #modified
*
* #description function-hoisting.js
* #augments
* #example
* #link
*
*/
(function() {
const log = console.log;
var a = 1;
function b() {
a = 10;
log(`local a`, a)
return;
// function hoisting priority is greater than variable hoisting
function a() {}
}
b();
log(`global a`, a);
// local a 10
// global a 1
})();
which is equal to
(function() {
const log = console.log;
// define "a" in global scope
var a = 1;
function b() {
// define "a" in local scope
var a ;
// assign function to a
a = function () {};
// overwrites local variable "a"
a = 10;
log(`local a`, a);
return;
}
b();
// log global variable "a"
log(`global a`, a);
// local a 10
// global a 1
})();
the reason behind of hoisting
var a = 1;
//"a" is global scope
function b() {
var a = function () {};
//"a" is local scope
var x = 12;
//"x" is local scope
a = 10;
//global variable "a" was overwrited by the local variable "a"
console.log("local a =" + a);
return console.log("local x = " + x);
}
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x =
console.log(x);
// ReferenceError: x is not defined
/**
* scpope & closure & hoisting (var/function)
*
* 1. scpope : the global var can be access in any place(the whole file scope), local var only can be accessed by the local scope(function/block scope)!
* Note: if a local variable not using var keywords in a function, it will become a global variable!
*
* 2. closure : a function inner the other function, which can access local scope(parent function) & global scope, howerver it's vars can't be accessed by others! unless, your return it as return value!
*
* 3. hoisting : move all declare/undeclare vars/function to the scope top, than assign the value or null!
* Note: it just move the declare, not move the value!
*
*/
ES6 let, const no exist hoisting
(() => {
const log = console.log;
log(a)
// Error: Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 1;
})();
(() => {
const log = console.log;
log(b)
// Error: Uncaught ReferenceError: Cannot access 'b' before initialization
const b = 1;
})();
refs
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
I just read a great article about JavaScript Scoping and Hoisting by Ben Cherry in which he gives the following example:
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
Using the code above, the browser will alert "1".
I'm still unsure why it returns "1". Some of the things he says come to mind like:
All the function declarations are hoisted to the top. You can scope a variable using function. Still doesn't click for me.
Function hoisting means that functions are moved to the top of their scope. That is,
function b() {
a = 10;
return;
function a() {}
}
will be rewritten by the interpeter to this
function b() {
function a() {}
a = 10;
return;
}
Weird, eh?
Also, in this instance,
function a() {}
behaved the same as
var a = function () {};
So, in essence, this is what the code is doing:
var a = 1; //defines "a" in global scope
function b() {
var a = function () {}; //defines "a" in local scope
a = 10; //overwrites local variable "a"
return;
}
b();
alert(a); //alerts global variable "a"
What you have to remember is that it parses the whole function and resolves all the variables declarations before executing it. So....
function a() {}
really becomes
var a = function () {}
var a forces it into a local scope, and variable scope is through the entire function, so the global a variable is still 1 because you have declared a into a local scope by making it a function.
The function a is hoisted inside function b:
var a = 1;
function b() {
function a() {}
a = 10;
return;
}
b();
alert(a);
which is almost like using var:
var a = 1;
function b() {
var a = function () {};
a = 10;
return;
}
b();
alert(a);
The function is declared locally, and setting a only happens in the local scope, not the global var.
function declaration function a(){} is hoisted first and it behaves like var a = function () {};, hence in local scope a is created.
If you have two variable with same name (one in global another in local), local variable always get precedence over global variable.
When you set a=10, you are setting the local variable a , not the global one.
Hence, the value of global variable remain same and you get, alerted 1
Suprisingly, none of the answers here mention the relevancy of the Execution Context in the Scope Chain.
The JavaScript Engine wraps the currently executing code in an Execution Context. The base execution context is the global Execution Context. Each time a new function is invoked, a new Execution Context is created and put on the Execution Stack. Think of a Stack Frame sitting on an Invocation Stack in other programming languages. Last in first out. Now each Execution Context has its own Variable Environment and Outer Environment in JavaScript.
I will use the below example as a demonstration.
1) First, we enter the Creation Phase of the global Execution Context. Both the Outer Environment and Variable Environment of the Lexical Environment are created. The Global Object is setup and placed in memory with the special variable 'this' pointing to it. The function a and its code and the variable myVar with an undefined value are placed in memory in the global Variable Environment. it's important to note that function a's code is not executed. It is just placed in memory with function a.
2) Second, it is the Execution Phase of the Execution Context. myVar is no longer an undefined value. It is initialized with value of 1, which is stored in the global Variable Environment. The function a is invoked and a new Execution Context is created.
3) In the function a's Execution Context, it goes through the Creation and Execution Phase of its own Execution Context. It has its own Outer Environment and Variable Environment, thus, its own Lexical Environment. The function b and the variable myVar are stored in its Variable Environment. This Variable Environment is distinct from the global Variable Environment. Since the function a sits lexically (physically in code) on the same level as the global Execution Context, its Outer Environment is the global Execution Context. Thus, if the function a was to refer to a variable that is not in its Variable Environment, it will search the Scope Chain and try to find the variable in the Variable Environment of the global Execution Context.
4) The function b is invoked in function a. A new Execution Context is created. Since it sits lexically in function a, its Outer Environment is a. So when it references myVar, since myVar is not in function b's Variable Environment, it will look in function a's Variable Environment. It finds it there and console.log prints 2. But if the variable was not in function a's Variable Environment, then since function a's Outer Environment is the global Execution Context, then the Scope Chain will continue searching there.
5) After function b and a are finished execution, they are popped from the Execution Stack. The single-threaded JavaScript Engine continues execution at the global Execution Context. It invokes the b function. But there is no b function in the global Variable Environment and there is no other Outer Environment to search in the global Execution Context. Thus an exception is raised by the JavaScript Engine.
function a(){
function b(){
console.log(myVar);
}
var myVar = 2;
b();
}
var myVar = 1;
a();
b();
> 2
> Uncaught ReferenceError: b is not defined
The below example shows the Scope Chain in action. In the function b's Execution Context's Variable Environment, there is no myVar. So it searches its Outer Environment, which is the function a. The function a does not have myVar in its Variable Environment either. So the Engine searches function a's Outer Environment, which is the global Execution Context's Outer Environment and myVar is defined there. Hence, the console.log prints 1.
function a(){
function b(){
console.log(myVar);
}
b();
}
var myVar = 1;
a();
> 1
Regarding Execution Context and the Lexical Environment associated with it, including Outer Environment and Variable Environment, enable the scoping of variables in JavaScript. Even if you invoke the same function multiple times, for each invocation, it will create its own Execution Context. So each Execution Context will have its own copy of the variables in its Variable Environment. There is no sharing of variables.
function a() { } is a function statement, which creates an a variable local to the b function.
Variables are created when a function is parsed, regardless of whether the var or function statement gets executed.
a = 10 sets this local variable.
What is the bone of contention in this small snippet of code?
Case 1:
Include function a(){} definition inside the body of function b as follows. logs value of a = 1
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
console.log(a); // logs a = 1
Case 2
Exclude function a(){} definition inside the body of function b as follows. logs value of a = 10
var a = 1;
function b() {
a = 10; // overwrites the value of global 'var a'
return;
}
b();
console.log(a); // logs a = 10
Observation will help you realise that statement console.log(a) logs the following values.
Case 1 : a = 1
Case 2 : a = 10
Posits
var a has been defined and declared lexically in the global scope.
a=10 This statement is reassigning value to 10, it lexically sits inside the function b.
Explanation of both the cases
Because of function definition with name property a is same as the variable a. The variable a inside the function body b becomes a local variable. The previous line implies that the global value of a remains intact and the local value of a is updated to 10.
So, what we intend to say is that the code below
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
console.log(a); // logs a = 1
It is interpreted by the JS interpreter as follows.
var a = 1;
function b() {
function a() {}
a = 10;
return;
}
b();
console.log(a); // logs a = 1
However, when we remove the function a(){} definition, the value of 'a' declared and defined outside the function b, that value gets overwritten and it changes to 10 in case 2. The value gets overwritten because a=10 refers to the global declaration and if it were to be declared locally we must have written var a = 10;.
var a = 1;
function b() {
var a = 10; // here var a is declared and defined locally because it uses a var keyword.
return;
}
b();
console.log(a); // logs a = 1
We can clarify our doubt further by changing the name property in function a(){} definition to some other name than 'a'
var a = 1;
function b() {
a = 10; // here var a is declared and defined locally because it uses a var keyword.
return;
function foo() {}
}
b();
console.log(a); // logs a = 1
Hoisting is a concept made for us to make it easier to understand. What actually happens is the declarations are done first with respect to their scopes and the assignments will happen after that(not at the same time).
When the declarations happen, var a, then function b and inside that b scope, function a is declared.
This function a will shadow the variable a coming from the global scope.
After the declarations are done, the values assign will start, the global a will get the value 1 and the a inside function b will get 10.
when you do alert(a), it will call the actual global scope variable.
This little change to the code will make it more clear
var a = 1;
function b() {
a = 10;
return a;
function a() { }
}
alert(b());
alert(a);
It is happening because of the Variable name is same as the function name means "a".
Thus due to Javascript hoisting it try to solve the naming conflict and it will return a = 1.
I was also confused about this until i read this post on "JavaScript Hoisting" http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html
Hope it helps.
Here's my recap of the answer with more annotation and an acompaniying fiddle to play around with.
// hoisting_example.js
// top of scope ie. global var a = 1
var a = 1;
// new scope due to js' functional (not block) level scope
function b() {
a = 10; // if the function 'a' didn't exist in this scope, global a = 10
return; // the return illustrates that function 'a' is hoisted to top
function a(){}; // 'a' will be hoisted to top as var a = function(){};
}
// exec 'b' and you would expect to see a = 10 in subsequent alert
// but the interpreter acutally 'hoisted' the function 'a' within 'b'
// and in doing so, created a new named variable 'a'
// which is a function within b's scope
b();
// a will alert 1, see comment above
alert(a);
https://jsfiddle.net/adjavaherian/fffpxjx7/
scpope & closure & hoisting (var/function)
scpope : the global var can be access in any place(the whole file
scope), local var only can be accessed by the local
scope(function/block scope)!
Note: if a local variable not using
var keywords in a function, it will become a global variable!
closure : a function inner the other function, which can access
local scope(parent function) & global scope, howerver it's vars
can't be accessed by others! unless, your return it as return value!
hoisting : move all declare/undeclare vars/function to the scope
top, than assign the value or null!
Note: it just move the declare,not move the value!
var a = 1;
//"a" is global scope
function b() {
var a = function () {};
//"a" is local scope
var x = 12;
//"x" is local scope
a = 10;
//global variable "a" was overwrited by the local variable "a"
console.log("local a =" + a);
return console.log("local x = " + x);
}
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x =
console.log(x);
// ReferenceError: x is not defined
Hoisting In JavaScript means, variable declarations are executed through out the program before any code is executed. Therefore declaring a variable anywhere in the code is equivalent to declaring it at the beginning.
Its all depends on the scope of variable 'a'. Let me explain by creating scopes as images.
Here JavaScript will create 3 scopes.
i) Global scope.
ii) Function b() scope.
iii) Function a() scope.
Its clear when you call 'alert' method scope belongs to Global that time, so it will pick value of variable 'a' from Global scope only that is 1.
Long Post!
But it will clear the air!
The way Java Script works is that it involves a two step process:
Compilation(so to speak) - This step registers variables and function declarations and their respective scope. It does not involve evaluating function expression: var a = function(){} or variable expression (like assigning 3 to x in case of var x =3; which is nothing but the evaluation of R.H.S part.)
Interpreter: This is the execution/evaluation part.
Check the output of below code to get an understanding:
//b() can be called here!
//c() cannot be called.
console.log("a is " + a);
console.log("b is " + b);
console.log("c is " + c);
var a = 1;
console.log("Now, a is " + a);
var c = function() {};
console.log("Now c is " + c);
function b() {
//cannot write the below line:
//console.log(e);
//since e is not declared.
e = 10; //Java script interpreter after traversing from this function scope chain to global scope, is unable to find this variable and eventually initialises it with value 10 in global scope.
console.log("e is " + e) // works!
console.log("f is " + f);
var f = 7;
console.log("Now f is " + f);
console.log("d is " + d);
return;
function d() {}
}
b();
console.log(a);
Lets break it:
In the compilation phase,
'a' would be registered under global scope with value 'undefined'.
Same goes for 'c', its value at this moment would be 'undefined' and not the 'function()'.
'b' would be registered as a function in the global scope.
Inside b's scope, 'f' would be registered as a variable which would be undefined at this moment and function 'd' would be registered.
When interpreter runs, declared variables and function() (and not expressions) can be accessed before the interpreter reaches the actual expression line. So, variables would be printed 'undefined' and declared anonymous function can be called earlier. However, trying to access undeclared variable before its expression initialisation would result in an error like:
console.log(e)
e = 3;
Now, what happens when you have variable and function declaration with same name.
Answer is - functions are always hoisted before and if the same name variable is declared, it is treated as duplicate and ignored. Remember, order does not matter. Functions are always given precedence. But during evaluation phase you can change the variable reference to anything (It stores whatever was the last assignment) Have a look at the below code:
var a = 1;
console.log("a is " + a);
function b() {
console.log("a inside the function b is " + a); //interpreter finds 'a' as function() in current scope. No need to go outside the scope to find 'a'.
a = 3; //a changed
console.log("Now a is " + a);
return;
function a() {}
}
var a; //treated as duplicate and ignored.
b();
console.log("a is still " + a + " in global scope"); //This is global scope a.
Hoisting is behavioural concept of JavaScript. Hoisting (say moving) is concept that explains how and where variables should be declared.
In JavaScript, a variable can be declared after it has been used because Function declarations and variable declarations are always moved (“hoisted”) invisibly to the top of their containing scope by the JavaScript interpreter.
We encounter two types of hoisting in most cases.
1.Variable declaration hoisting
Lets understand this by this piece of code.
a = 5; // Assign 5 to a
elem = document.getElementById("demo"); // Find an element
elem.innerHTML = a; // Display a in the element
var a; // Declare a
//output-> 5
Here declaration of variable a will be hosted to top invisibly by the javascript interpreter at the time of compilation. So we were able to get value of a. But this approach of declaration of variables is not recommended as we should declare variables to top already like this.
var a = 5; // Assign and declare 5 to a
elem = document.getElementById("demo"); // Find an element
elem.innerHTML = a; // Display a in the element
// output -> 5
consider another example.
function foo() {
console.log(x)
var x = 1;
}
is actually interpreted like this:
function foo() {
var x;
console.log(x)
x = 1;
}
In this case x will be undefined
It does not matter if the code has executed which contains the declaration of variable. Consider this example.
function foo() {
if (false) {
var a = 1;
}
return;
var b = 1;
}
This function turns out to be like this.
function foo() {
var a, b;
if (false) {
a = 1;
}
return;
b = 1;
}
In variable declaration only variable definition hoists, not the assignment.
Function declaration hoisting
Unlike the variable hoisting the function body or assigned value will also be hoisted. Consider this code
function demo() {
foo(); // this will give error because it is variable hoisting
bar(); // "this will run!" as it is function hoisting
var foo = function () {
alert("this would not run!!");
}
function bar() {
alert("this will run!!");
}
}
demo();
Now as we understood both variable and function hoisting, let's understand this code now.
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
This code will turn out to be like this.
var a = 1; //defines "a" in global scope
function b() {
var a = function () {}; //defines "a" in local scope
a = 10; //overwrites local variable "a"
return;
}
b();
alert(a);
The function a() will have local scope inside b(). a() will be moved to top while interpreting the code with its definition (only in case of function hoisting) so a now will have local scope and therefore will not affect the global scope of a while having its own scope inside function b().
From my piece of knowledge, hoisting happens with the variable declaration and function declaration, for example:
a = 7;
var a;
console.log(a)
What happens inside JavaScript's engine:
var a;
a = 7;
console.log(a);
// 7
Or:
console.log(square(7)); // Output: 49
function square(n) { return n * n; }
It will become:
function square(n) { return n * n; }
console.log(square(7)); // 49
But assignments such as variable assigment, function expression assignment will not be hoisted:
For example:
console.log(x);
var x = 7; // undefined
It may become like this:
var x;
console.log(x); // undefined
x = 7;
To describe hosting in javascript in one sentence is variables and functions are hoisted to the top of the scope that they are declared in.
I am assuming you are a beginner, to understand hoisting properly at first we have understood the difference between undefined and ReferenceError
var v;
console.log(v);
console.log(abc);
/*
The output of the above codes are:
undefined
ReferenceError: abc is not defined*/
now in the bellow code what we see? a variable and a function expression is decleard.
<script>
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
</script>
but the real picture with proof that the both variable and function are hoisted on the top of there scope:
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));
Output of first two logs are undefined and TypeError: getSum is not a function because both var totalAmo and getSum are hoisted on the top of their scope like bellow
<script>
var totalAmo;
var getSum;
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));
</script>
But for functions declaration whole functions hoisted on the top of their scope.
console.log(getId());
function getId(){
return 739373;
}
/* output: 739373, because the whole function hoisted on the top of the scope.*/
Now the same logic goes for those varibale, functions experessions and function declaratoins declared inside functional scope. Key point: they will not be hoisted on the top of the file;
function functionScope(){
var totalAmo;
var getSum;
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
}
So, when you use var keyword, variable and function hoisted on the top of there scope (global scope and function scope).
What about let and const, const and let are still both aware of the global scope and function scope just like var is, but const and let variables are also aware of another scope called blocked scope. a block scope is present whenever there is a block of code, such as for loop, if else statement, while loop etc.
When we use const and let to declare a variable in these block scope, the variable declaration only will be hoisted on the top of that block that it is in, and it will not be hoisted on the top of the parent function or top of the global scope that it is hoisted.
function getTotal(){
let total=0;
for(var i = 0; i<10; i++){
let valueToAdd = i;
var multiplier = 2;
total += valueToAdd*multiplier;
}
return total;
}
Variables in abobe example will be hoisted like bellow
function getTotal(){
let total;
var multiplier;
total = 0;
for(var i = 0; i<10; i++){
let valueToAdd;
valueToAdd = i;
multiplier = 2;
total += valueToAdd*multiplier;
}
return total;
}
ES5: function hoisting & variable hoisting
function hoisting priority is greater than variable hoisting
"use strict";
/**
*
* #author xgqfrms
* #license MIT
* #copyright xgqfrms
* #created 2016-06-01
* #modified
*
* #description function-hoisting.js
* #augments
* #example
* #link
*
*/
(function() {
const log = console.log;
var a = 1;
function b() {
a = 10;
log(`local a`, a)
return;
// function hoisting priority is greater than variable hoisting
function a() {}
}
b();
log(`global a`, a);
// local a 10
// global a 1
})();
which is equal to
(function() {
const log = console.log;
// define "a" in global scope
var a = 1;
function b() {
// define "a" in local scope
var a ;
// assign function to a
a = function () {};
// overwrites local variable "a"
a = 10;
log(`local a`, a);
return;
}
b();
// log global variable "a"
log(`global a`, a);
// local a 10
// global a 1
})();
the reason behind of hoisting
var a = 1;
//"a" is global scope
function b() {
var a = function () {};
//"a" is local scope
var x = 12;
//"x" is local scope
a = 10;
//global variable "a" was overwrited by the local variable "a"
console.log("local a =" + a);
return console.log("local x = " + x);
}
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x =
console.log(x);
// ReferenceError: x is not defined
/**
* scpope & closure & hoisting (var/function)
*
* 1. scpope : the global var can be access in any place(the whole file scope), local var only can be accessed by the local scope(function/block scope)!
* Note: if a local variable not using var keywords in a function, it will become a global variable!
*
* 2. closure : a function inner the other function, which can access local scope(parent function) & global scope, howerver it's vars can't be accessed by others! unless, your return it as return value!
*
* 3. hoisting : move all declare/undeclare vars/function to the scope top, than assign the value or null!
* Note: it just move the declare, not move the value!
*
*/
ES6 let, const no exist hoisting
(() => {
const log = console.log;
log(a)
// Error: Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 1;
})();
(() => {
const log = console.log;
log(b)
// Error: Uncaught ReferenceError: Cannot access 'b' before initialization
const b = 1;
})();
refs
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
I can't understand why variables act so strange when declared inside a function.
In the first function I declare with let the variables b and c with the value 10:
b = c = 10;
In the second function I show:
b + ", " + c
And this shows:
10, 10
Also in first function I declare a with value 10:
let a = b = c = 10;
But in the second function it shows an error:
Can't find variable: a
Now in the first function I declare d with value 20:
var d = 20;
But in the second function it shows the same error as before, but with the variable d:
Can't find variable: d
Example:
function first() {
let a = b = c = 10;
var d = 20;
second();
}
function second() {
console.log(b + ", " + c); //shows "10, 10"
try{ console.log(a); } // Rreference error
catch(e){ console.error(e.message) }
try{ console.log(d); } // Reference error
catch(e){ console.error(e.message) }
}
first()
It's because you're actually saying:
c = 10;
b = c;
let a = b;
And not what you think you are saying, which is:
let a = 10;
let b = 10;
let c = 10;
You'll notice that no matter how many variables you add to your chain, it will only be the first (a) that causes the error.
This is because "let" scopes your variable to the block (or, "locally", more or less meaning "in the brackets") in which you declare it.
If you declare a variable without "let", it scopes the variable globally.
So, in the function where you set your variables, everything gets the value 10 (you can see this in the debugger if you put a breakpoint). If you put a console log for a,b,c in that first function, all is well.
But as soon as you leave that function, the first one (a)--and again, keep in mind, technically in the order of assignment, it is the last one-- "disappears" (again, you can see this in the debugger if you set a breakpoint in the second function), but the other two (or however many you add) are still available.
This is because, "let" ONLY APPLIES TO (so only locally scopes) THE FIRST VARIABLE--again, which is technically the last to be declared and assigned a value--in the chain. The rest technically do not have "let" in front of them. So those are technically declared globally (that is, on the global object), which is why they appear in your second function.
Try it: remove the "let" keyword. All your vars will now be available.
"var" has a similar local-scope effect, but differs in how the variable is "hoisted", which is something you should definitely understand, but which is not directly involved with your question.
(BTW, this question would stump enough pro JS devs to make it a good one).
Strongly suggest you spend time with the differences in how variables can be declared in JS: without a keyword, with "let", and with "var".
In the function first(), variables band c are created on the fly, without using var or let.
let a = b = c = 10; // b and c are created on the fly
Is different than
let a = 10, b = 10, c = 10; // b and c are created using let (note the ,)
They become implicit global. That's why they are available in second()
From documentation
Assigning a value to an undeclared variable implicitly creates it as a global variable (it becomes a property of the global object) when the assignment is executed.
To avoid this, you can use "use strict" that will provide errors when one use an undeclared variable
"use strict"; // <-------------- check this
function first() {
/*
* With "use strict" c is not defined.
* (Neither is b, but since the line will be executed from right to left,
* the variable c will cause the error and the script will stop)
* Without, b and c become globals, and then are accessible in other functions
*/
let a = b = c = 10;
var d = 20;
second();
}
function second() {
console.log(b + ", " + c); //reference error
console.log(a); //reference error
console.log(d); //reference error
}
first();
Before calling things strange, let’s know some basics first:
var and let are both used for variable declaration in JavaScript. For example,
var one = 1;
let two = 2;
Variables can also be declared without using var or let. For example,
three = 3;
Now the difference between the above approaches is that:
var is function scoped
and
let is block scoped.
while the scope of the variables declared without var/let keyword
become global irrespective of where it is declared.
Global variables can be accessed from anywhere in the web page (not recommended because globals can be accidentally modified).
Now according to these concepts let's have a look at the code in question:
function first() {
let a = b = c = 10;
/* The above line means:
let a=10; // Block scope
b=10; // Global scope
c=10; // Global scope
*/
var d = 20; // Function scope
second();
}
function second() {
alert(b + ", " + c); // Shows "10, 10" //accessible because of global scope
alert(a); // Error not accessible because block scope has ended
alert(d); // Error not accessible because function scope has ended
}
Variables using the let keyword should only be available within the scope of the block and not available in an outside function...
Each variable that you are declaring in that manner is not using let or var. You are missing a comma in the variables declaration.
It is not recommended to declare a variable without the var keyword. It can accidentally overwrite an existing global variable. The scope of the variables declared without the var keyword become global irrespective of where it is declared. Global variables can be accessed from anywhere in the web page.
function first() {
let a = 10;
let b = 10;
let c = 10;
var d = 20;
second();
}
function second() {
console.log(b + ", " + c); //shows "10, 10"
console.log(a); //reference error
console.log(d); //reference error
}
first();
It's because of when you don't use let or var then variable is getting declare on the fly, better you declare like following.
let a = 10;
let b = 10;
let c = 10;
The strange issue is caused by scoping rules in JavaScript
function first() {
let a = b = c = 10; // a is in local scope, b and c are in global scope
var d = 20; // d is in local scope
second(); // will have access to b and c from the global scope
}
Assuming that you want to declare 3 local variables initialised to the same value (100). Your first() will look like below. In this case, second() will not have access to any of the variables because they are local to first()
function first() {
let a = 100; // a is in local scope init to 100
let b = a; // b is in local scope init to a
let c = b // c is in local scope init to b
var d = 20; // d is in local scope
second(); // will not have access a, b, c, or d
}
However, if you want global variables then your first() will look like below. In this case, second will have access to all the variables because they are in global scope
function first() {
a = 100; // a is in global scope
b = a; // b is in global scope
c = b // c is in global scope
d = 20; // d is in global scope
second(); // will have access to a, b, c, and d from the global scope
}
Local variables (aka. accessible in the code block where they are declared). A Code block is any {} with line(s) of code between.
function() {var, let, const in here is accessible to entire function},
for() {var in here is accessible to outer scope, let, const accessible only in here},
etc.
Global variables (aka accessible in the global scope).
These variables are attached to the global object. The global object is environment dependent. It is the window object in browsers.
Special note: You can declare variables in JavaScript without using the var, let, const keywords. A variable declared this way is attached to the global object, therefore accessible in the global scope.
a = 100 // is valid and is in global scope
Some articles for further reading:
https://www.sitepoint.com/demystifying-javascript-variable-scope-hoisting/
https://scotch.io/tutorials/understanding-scope-in-javascript
https://www.digitalocean.com/community/tutorials/understanding-variables-scope-hoisting-in-javascript
Main difference is scoping rules. Variables declared by var keyword are scoped to the immediate function body (hence the function scope) while let variables are scoped to the immediate enclosing block denoted by { } (hence the block scope). And when you say
c = 10;
b = c;
let a = b;
c and b have the life span as fun have but a only have block span and if you try to access a by referencing it always show error but c and b are globally so they don't.You'll notice that no matter how many variables you add to your chain, it will only be the first (a) that causes the error.This is because "let" scopes your variable to the block (or, "locally", more or less meaning "in the brackets") in which you declare it.If you declare a variable without "let", it scopes the variable globally.So, in the function where you set your variables, everything gets the value 10 (you can see this in the debugger if you put a break-point). If you put a console log for a,b,c in that first function, all is well.But as soon as you leave that function, the first one (a)--and again, keep in mind, technically in the order of assignment, it is the last one-- "disappears" (again, you can see this in the debugger if you set a break-point in the second function), but the other two (or however many you add) are still available.
Here are the 3 interesting aspects of variable declarations in JavaScript:
var restricts the scope of variable to the block in which it is defined. ('var' is for local scope.)
let allows temporary overriding of an external variable's value inside a block.
Simply declaring a variable without var or let will make the
variable global, regardless of where it is declared.
Here is a demo of let, which is the latest addition to the language:
// File name: let_demo.js
function first() {
a = b = 10
console.log("First function: a = " + a)
console.log("First function: a + b = " + (a + b))
}
function second() {
let a = 5
console.log("Second function: a = " + a)
console.log("Second function: a + b = " + (a + b))
}
first()
second()
console.log("Global: a = " + a)
console.log("Global: a + b = " + (a + b))
Output:
$ node let_demo.js
First function: a = 10
First function: a + b = 20
Second function: a = 5
Second function: a + b = 15
Global: a = 10
Global: a + b = 20
Explanation:
The variables a and b were delcared inside 'first()', without var or let keywords.
Therefore, a and b are global, and hence, are accessible throughout the program.
In function named 'second', the statement 'let a = 5' temporarily sets the value of 'a' to '5', within the scope of the function only.
Outside the scope of 'second()', I.E., in the global scope, the value of 'a' will be as defined earlier.
I just read a great article about JavaScript Scoping and Hoisting by Ben Cherry in which he gives the following example:
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
Using the code above, the browser will alert "1".
I'm still unsure why it returns "1". Some of the things he says come to mind like:
All the function declarations are hoisted to the top. You can scope a variable using function. Still doesn't click for me.
Function hoisting means that functions are moved to the top of their scope. That is,
function b() {
a = 10;
return;
function a() {}
}
will be rewritten by the interpeter to this
function b() {
function a() {}
a = 10;
return;
}
Weird, eh?
Also, in this instance,
function a() {}
behaved the same as
var a = function () {};
So, in essence, this is what the code is doing:
var a = 1; //defines "a" in global scope
function b() {
var a = function () {}; //defines "a" in local scope
a = 10; //overwrites local variable "a"
return;
}
b();
alert(a); //alerts global variable "a"
What you have to remember is that it parses the whole function and resolves all the variables declarations before executing it. So....
function a() {}
really becomes
var a = function () {}
var a forces it into a local scope, and variable scope is through the entire function, so the global a variable is still 1 because you have declared a into a local scope by making it a function.
The function a is hoisted inside function b:
var a = 1;
function b() {
function a() {}
a = 10;
return;
}
b();
alert(a);
which is almost like using var:
var a = 1;
function b() {
var a = function () {};
a = 10;
return;
}
b();
alert(a);
The function is declared locally, and setting a only happens in the local scope, not the global var.
function declaration function a(){} is hoisted first and it behaves like var a = function () {};, hence in local scope a is created.
If you have two variable with same name (one in global another in local), local variable always get precedence over global variable.
When you set a=10, you are setting the local variable a , not the global one.
Hence, the value of global variable remain same and you get, alerted 1
Suprisingly, none of the answers here mention the relevancy of the Execution Context in the Scope Chain.
The JavaScript Engine wraps the currently executing code in an Execution Context. The base execution context is the global Execution Context. Each time a new function is invoked, a new Execution Context is created and put on the Execution Stack. Think of a Stack Frame sitting on an Invocation Stack in other programming languages. Last in first out. Now each Execution Context has its own Variable Environment and Outer Environment in JavaScript.
I will use the below example as a demonstration.
1) First, we enter the Creation Phase of the global Execution Context. Both the Outer Environment and Variable Environment of the Lexical Environment are created. The Global Object is setup and placed in memory with the special variable 'this' pointing to it. The function a and its code and the variable myVar with an undefined value are placed in memory in the global Variable Environment. it's important to note that function a's code is not executed. It is just placed in memory with function a.
2) Second, it is the Execution Phase of the Execution Context. myVar is no longer an undefined value. It is initialized with value of 1, which is stored in the global Variable Environment. The function a is invoked and a new Execution Context is created.
3) In the function a's Execution Context, it goes through the Creation and Execution Phase of its own Execution Context. It has its own Outer Environment and Variable Environment, thus, its own Lexical Environment. The function b and the variable myVar are stored in its Variable Environment. This Variable Environment is distinct from the global Variable Environment. Since the function a sits lexically (physically in code) on the same level as the global Execution Context, its Outer Environment is the global Execution Context. Thus, if the function a was to refer to a variable that is not in its Variable Environment, it will search the Scope Chain and try to find the variable in the Variable Environment of the global Execution Context.
4) The function b is invoked in function a. A new Execution Context is created. Since it sits lexically in function a, its Outer Environment is a. So when it references myVar, since myVar is not in function b's Variable Environment, it will look in function a's Variable Environment. It finds it there and console.log prints 2. But if the variable was not in function a's Variable Environment, then since function a's Outer Environment is the global Execution Context, then the Scope Chain will continue searching there.
5) After function b and a are finished execution, they are popped from the Execution Stack. The single-threaded JavaScript Engine continues execution at the global Execution Context. It invokes the b function. But there is no b function in the global Variable Environment and there is no other Outer Environment to search in the global Execution Context. Thus an exception is raised by the JavaScript Engine.
function a(){
function b(){
console.log(myVar);
}
var myVar = 2;
b();
}
var myVar = 1;
a();
b();
> 2
> Uncaught ReferenceError: b is not defined
The below example shows the Scope Chain in action. In the function b's Execution Context's Variable Environment, there is no myVar. So it searches its Outer Environment, which is the function a. The function a does not have myVar in its Variable Environment either. So the Engine searches function a's Outer Environment, which is the global Execution Context's Outer Environment and myVar is defined there. Hence, the console.log prints 1.
function a(){
function b(){
console.log(myVar);
}
b();
}
var myVar = 1;
a();
> 1
Regarding Execution Context and the Lexical Environment associated with it, including Outer Environment and Variable Environment, enable the scoping of variables in JavaScript. Even if you invoke the same function multiple times, for each invocation, it will create its own Execution Context. So each Execution Context will have its own copy of the variables in its Variable Environment. There is no sharing of variables.
function a() { } is a function statement, which creates an a variable local to the b function.
Variables are created when a function is parsed, regardless of whether the var or function statement gets executed.
a = 10 sets this local variable.
What is the bone of contention in this small snippet of code?
Case 1:
Include function a(){} definition inside the body of function b as follows. logs value of a = 1
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
console.log(a); // logs a = 1
Case 2
Exclude function a(){} definition inside the body of function b as follows. logs value of a = 10
var a = 1;
function b() {
a = 10; // overwrites the value of global 'var a'
return;
}
b();
console.log(a); // logs a = 10
Observation will help you realise that statement console.log(a) logs the following values.
Case 1 : a = 1
Case 2 : a = 10
Posits
var a has been defined and declared lexically in the global scope.
a=10 This statement is reassigning value to 10, it lexically sits inside the function b.
Explanation of both the cases
Because of function definition with name property a is same as the variable a. The variable a inside the function body b becomes a local variable. The previous line implies that the global value of a remains intact and the local value of a is updated to 10.
So, what we intend to say is that the code below
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
console.log(a); // logs a = 1
It is interpreted by the JS interpreter as follows.
var a = 1;
function b() {
function a() {}
a = 10;
return;
}
b();
console.log(a); // logs a = 1
However, when we remove the function a(){} definition, the value of 'a' declared and defined outside the function b, that value gets overwritten and it changes to 10 in case 2. The value gets overwritten because a=10 refers to the global declaration and if it were to be declared locally we must have written var a = 10;.
var a = 1;
function b() {
var a = 10; // here var a is declared and defined locally because it uses a var keyword.
return;
}
b();
console.log(a); // logs a = 1
We can clarify our doubt further by changing the name property in function a(){} definition to some other name than 'a'
var a = 1;
function b() {
a = 10; // here var a is declared and defined locally because it uses a var keyword.
return;
function foo() {}
}
b();
console.log(a); // logs a = 1
Hoisting is a concept made for us to make it easier to understand. What actually happens is the declarations are done first with respect to their scopes and the assignments will happen after that(not at the same time).
When the declarations happen, var a, then function b and inside that b scope, function a is declared.
This function a will shadow the variable a coming from the global scope.
After the declarations are done, the values assign will start, the global a will get the value 1 and the a inside function b will get 10.
when you do alert(a), it will call the actual global scope variable.
This little change to the code will make it more clear
var a = 1;
function b() {
a = 10;
return a;
function a() { }
}
alert(b());
alert(a);
It is happening because of the Variable name is same as the function name means "a".
Thus due to Javascript hoisting it try to solve the naming conflict and it will return a = 1.
I was also confused about this until i read this post on "JavaScript Hoisting" http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html
Hope it helps.
Here's my recap of the answer with more annotation and an acompaniying fiddle to play around with.
// hoisting_example.js
// top of scope ie. global var a = 1
var a = 1;
// new scope due to js' functional (not block) level scope
function b() {
a = 10; // if the function 'a' didn't exist in this scope, global a = 10
return; // the return illustrates that function 'a' is hoisted to top
function a(){}; // 'a' will be hoisted to top as var a = function(){};
}
// exec 'b' and you would expect to see a = 10 in subsequent alert
// but the interpreter acutally 'hoisted' the function 'a' within 'b'
// and in doing so, created a new named variable 'a'
// which is a function within b's scope
b();
// a will alert 1, see comment above
alert(a);
https://jsfiddle.net/adjavaherian/fffpxjx7/
scpope & closure & hoisting (var/function)
scpope : the global var can be access in any place(the whole file
scope), local var only can be accessed by the local
scope(function/block scope)!
Note: if a local variable not using
var keywords in a function, it will become a global variable!
closure : a function inner the other function, which can access
local scope(parent function) & global scope, howerver it's vars
can't be accessed by others! unless, your return it as return value!
hoisting : move all declare/undeclare vars/function to the scope
top, than assign the value or null!
Note: it just move the declare,not move the value!
var a = 1;
//"a" is global scope
function b() {
var a = function () {};
//"a" is local scope
var x = 12;
//"x" is local scope
a = 10;
//global variable "a" was overwrited by the local variable "a"
console.log("local a =" + a);
return console.log("local x = " + x);
}
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x =
console.log(x);
// ReferenceError: x is not defined
Hoisting In JavaScript means, variable declarations are executed through out the program before any code is executed. Therefore declaring a variable anywhere in the code is equivalent to declaring it at the beginning.
Its all depends on the scope of variable 'a'. Let me explain by creating scopes as images.
Here JavaScript will create 3 scopes.
i) Global scope.
ii) Function b() scope.
iii) Function a() scope.
Its clear when you call 'alert' method scope belongs to Global that time, so it will pick value of variable 'a' from Global scope only that is 1.
Long Post!
But it will clear the air!
The way Java Script works is that it involves a two step process:
Compilation(so to speak) - This step registers variables and function declarations and their respective scope. It does not involve evaluating function expression: var a = function(){} or variable expression (like assigning 3 to x in case of var x =3; which is nothing but the evaluation of R.H.S part.)
Interpreter: This is the execution/evaluation part.
Check the output of below code to get an understanding:
//b() can be called here!
//c() cannot be called.
console.log("a is " + a);
console.log("b is " + b);
console.log("c is " + c);
var a = 1;
console.log("Now, a is " + a);
var c = function() {};
console.log("Now c is " + c);
function b() {
//cannot write the below line:
//console.log(e);
//since e is not declared.
e = 10; //Java script interpreter after traversing from this function scope chain to global scope, is unable to find this variable and eventually initialises it with value 10 in global scope.
console.log("e is " + e) // works!
console.log("f is " + f);
var f = 7;
console.log("Now f is " + f);
console.log("d is " + d);
return;
function d() {}
}
b();
console.log(a);
Lets break it:
In the compilation phase,
'a' would be registered under global scope with value 'undefined'.
Same goes for 'c', its value at this moment would be 'undefined' and not the 'function()'.
'b' would be registered as a function in the global scope.
Inside b's scope, 'f' would be registered as a variable which would be undefined at this moment and function 'd' would be registered.
When interpreter runs, declared variables and function() (and not expressions) can be accessed before the interpreter reaches the actual expression line. So, variables would be printed 'undefined' and declared anonymous function can be called earlier. However, trying to access undeclared variable before its expression initialisation would result in an error like:
console.log(e)
e = 3;
Now, what happens when you have variable and function declaration with same name.
Answer is - functions are always hoisted before and if the same name variable is declared, it is treated as duplicate and ignored. Remember, order does not matter. Functions are always given precedence. But during evaluation phase you can change the variable reference to anything (It stores whatever was the last assignment) Have a look at the below code:
var a = 1;
console.log("a is " + a);
function b() {
console.log("a inside the function b is " + a); //interpreter finds 'a' as function() in current scope. No need to go outside the scope to find 'a'.
a = 3; //a changed
console.log("Now a is " + a);
return;
function a() {}
}
var a; //treated as duplicate and ignored.
b();
console.log("a is still " + a + " in global scope"); //This is global scope a.
Hoisting is behavioural concept of JavaScript. Hoisting (say moving) is concept that explains how and where variables should be declared.
In JavaScript, a variable can be declared after it has been used because Function declarations and variable declarations are always moved (“hoisted”) invisibly to the top of their containing scope by the JavaScript interpreter.
We encounter two types of hoisting in most cases.
1.Variable declaration hoisting
Lets understand this by this piece of code.
a = 5; // Assign 5 to a
elem = document.getElementById("demo"); // Find an element
elem.innerHTML = a; // Display a in the element
var a; // Declare a
//output-> 5
Here declaration of variable a will be hosted to top invisibly by the javascript interpreter at the time of compilation. So we were able to get value of a. But this approach of declaration of variables is not recommended as we should declare variables to top already like this.
var a = 5; // Assign and declare 5 to a
elem = document.getElementById("demo"); // Find an element
elem.innerHTML = a; // Display a in the element
// output -> 5
consider another example.
function foo() {
console.log(x)
var x = 1;
}
is actually interpreted like this:
function foo() {
var x;
console.log(x)
x = 1;
}
In this case x will be undefined
It does not matter if the code has executed which contains the declaration of variable. Consider this example.
function foo() {
if (false) {
var a = 1;
}
return;
var b = 1;
}
This function turns out to be like this.
function foo() {
var a, b;
if (false) {
a = 1;
}
return;
b = 1;
}
In variable declaration only variable definition hoists, not the assignment.
Function declaration hoisting
Unlike the variable hoisting the function body or assigned value will also be hoisted. Consider this code
function demo() {
foo(); // this will give error because it is variable hoisting
bar(); // "this will run!" as it is function hoisting
var foo = function () {
alert("this would not run!!");
}
function bar() {
alert("this will run!!");
}
}
demo();
Now as we understood both variable and function hoisting, let's understand this code now.
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
This code will turn out to be like this.
var a = 1; //defines "a" in global scope
function b() {
var a = function () {}; //defines "a" in local scope
a = 10; //overwrites local variable "a"
return;
}
b();
alert(a);
The function a() will have local scope inside b(). a() will be moved to top while interpreting the code with its definition (only in case of function hoisting) so a now will have local scope and therefore will not affect the global scope of a while having its own scope inside function b().
From my piece of knowledge, hoisting happens with the variable declaration and function declaration, for example:
a = 7;
var a;
console.log(a)
What happens inside JavaScript's engine:
var a;
a = 7;
console.log(a);
// 7
Or:
console.log(square(7)); // Output: 49
function square(n) { return n * n; }
It will become:
function square(n) { return n * n; }
console.log(square(7)); // 49
But assignments such as variable assigment, function expression assignment will not be hoisted:
For example:
console.log(x);
var x = 7; // undefined
It may become like this:
var x;
console.log(x); // undefined
x = 7;
To describe hosting in javascript in one sentence is variables and functions are hoisted to the top of the scope that they are declared in.
I am assuming you are a beginner, to understand hoisting properly at first we have understood the difference between undefined and ReferenceError
var v;
console.log(v);
console.log(abc);
/*
The output of the above codes are:
undefined
ReferenceError: abc is not defined*/
now in the bellow code what we see? a variable and a function expression is decleard.
<script>
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
</script>
but the real picture with proof that the both variable and function are hoisted on the top of there scope:
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));
Output of first two logs are undefined and TypeError: getSum is not a function because both var totalAmo and getSum are hoisted on the top of their scope like bellow
<script>
var totalAmo;
var getSum;
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));
</script>
But for functions declaration whole functions hoisted on the top of their scope.
console.log(getId());
function getId(){
return 739373;
}
/* output: 739373, because the whole function hoisted on the top of the scope.*/
Now the same logic goes for those varibale, functions experessions and function declaratoins declared inside functional scope. Key point: they will not be hoisted on the top of the file;
function functionScope(){
var totalAmo;
var getSum;
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
}
So, when you use var keyword, variable and function hoisted on the top of there scope (global scope and function scope).
What about let and const, const and let are still both aware of the global scope and function scope just like var is, but const and let variables are also aware of another scope called blocked scope. a block scope is present whenever there is a block of code, such as for loop, if else statement, while loop etc.
When we use const and let to declare a variable in these block scope, the variable declaration only will be hoisted on the top of that block that it is in, and it will not be hoisted on the top of the parent function or top of the global scope that it is hoisted.
function getTotal(){
let total=0;
for(var i = 0; i<10; i++){
let valueToAdd = i;
var multiplier = 2;
total += valueToAdd*multiplier;
}
return total;
}
Variables in abobe example will be hoisted like bellow
function getTotal(){
let total;
var multiplier;
total = 0;
for(var i = 0; i<10; i++){
let valueToAdd;
valueToAdd = i;
multiplier = 2;
total += valueToAdd*multiplier;
}
return total;
}
ES5: function hoisting & variable hoisting
function hoisting priority is greater than variable hoisting
"use strict";
/**
*
* #author xgqfrms
* #license MIT
* #copyright xgqfrms
* #created 2016-06-01
* #modified
*
* #description function-hoisting.js
* #augments
* #example
* #link
*
*/
(function() {
const log = console.log;
var a = 1;
function b() {
a = 10;
log(`local a`, a)
return;
// function hoisting priority is greater than variable hoisting
function a() {}
}
b();
log(`global a`, a);
// local a 10
// global a 1
})();
which is equal to
(function() {
const log = console.log;
// define "a" in global scope
var a = 1;
function b() {
// define "a" in local scope
var a ;
// assign function to a
a = function () {};
// overwrites local variable "a"
a = 10;
log(`local a`, a);
return;
}
b();
// log global variable "a"
log(`global a`, a);
// local a 10
// global a 1
})();
the reason behind of hoisting
var a = 1;
//"a" is global scope
function b() {
var a = function () {};
//"a" is local scope
var x = 12;
//"x" is local scope
a = 10;
//global variable "a" was overwrited by the local variable "a"
console.log("local a =" + a);
return console.log("local x = " + x);
}
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x =
console.log(x);
// ReferenceError: x is not defined
/**
* scpope & closure & hoisting (var/function)
*
* 1. scpope : the global var can be access in any place(the whole file scope), local var only can be accessed by the local scope(function/block scope)!
* Note: if a local variable not using var keywords in a function, it will become a global variable!
*
* 2. closure : a function inner the other function, which can access local scope(parent function) & global scope, howerver it's vars can't be accessed by others! unless, your return it as return value!
*
* 3. hoisting : move all declare/undeclare vars/function to the scope top, than assign the value or null!
* Note: it just move the declare, not move the value!
*
*/
ES6 let, const no exist hoisting
(() => {
const log = console.log;
log(a)
// Error: Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 1;
})();
(() => {
const log = console.log;
log(b)
// Error: Uncaught ReferenceError: Cannot access 'b' before initialization
const b = 1;
})();
refs
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
I just read a great article about JavaScript Scoping and Hoisting by Ben Cherry in which he gives the following example:
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
Using the code above, the browser will alert "1".
I'm still unsure why it returns "1". Some of the things he says come to mind like:
All the function declarations are hoisted to the top. You can scope a variable using function. Still doesn't click for me.
Function hoisting means that functions are moved to the top of their scope. That is,
function b() {
a = 10;
return;
function a() {}
}
will be rewritten by the interpeter to this
function b() {
function a() {}
a = 10;
return;
}
Weird, eh?
Also, in this instance,
function a() {}
behaved the same as
var a = function () {};
So, in essence, this is what the code is doing:
var a = 1; //defines "a" in global scope
function b() {
var a = function () {}; //defines "a" in local scope
a = 10; //overwrites local variable "a"
return;
}
b();
alert(a); //alerts global variable "a"
What you have to remember is that it parses the whole function and resolves all the variables declarations before executing it. So....
function a() {}
really becomes
var a = function () {}
var a forces it into a local scope, and variable scope is through the entire function, so the global a variable is still 1 because you have declared a into a local scope by making it a function.
The function a is hoisted inside function b:
var a = 1;
function b() {
function a() {}
a = 10;
return;
}
b();
alert(a);
which is almost like using var:
var a = 1;
function b() {
var a = function () {};
a = 10;
return;
}
b();
alert(a);
The function is declared locally, and setting a only happens in the local scope, not the global var.
function declaration function a(){} is hoisted first and it behaves like var a = function () {};, hence in local scope a is created.
If you have two variable with same name (one in global another in local), local variable always get precedence over global variable.
When you set a=10, you are setting the local variable a , not the global one.
Hence, the value of global variable remain same and you get, alerted 1
Suprisingly, none of the answers here mention the relevancy of the Execution Context in the Scope Chain.
The JavaScript Engine wraps the currently executing code in an Execution Context. The base execution context is the global Execution Context. Each time a new function is invoked, a new Execution Context is created and put on the Execution Stack. Think of a Stack Frame sitting on an Invocation Stack in other programming languages. Last in first out. Now each Execution Context has its own Variable Environment and Outer Environment in JavaScript.
I will use the below example as a demonstration.
1) First, we enter the Creation Phase of the global Execution Context. Both the Outer Environment and Variable Environment of the Lexical Environment are created. The Global Object is setup and placed in memory with the special variable 'this' pointing to it. The function a and its code and the variable myVar with an undefined value are placed in memory in the global Variable Environment. it's important to note that function a's code is not executed. It is just placed in memory with function a.
2) Second, it is the Execution Phase of the Execution Context. myVar is no longer an undefined value. It is initialized with value of 1, which is stored in the global Variable Environment. The function a is invoked and a new Execution Context is created.
3) In the function a's Execution Context, it goes through the Creation and Execution Phase of its own Execution Context. It has its own Outer Environment and Variable Environment, thus, its own Lexical Environment. The function b and the variable myVar are stored in its Variable Environment. This Variable Environment is distinct from the global Variable Environment. Since the function a sits lexically (physically in code) on the same level as the global Execution Context, its Outer Environment is the global Execution Context. Thus, if the function a was to refer to a variable that is not in its Variable Environment, it will search the Scope Chain and try to find the variable in the Variable Environment of the global Execution Context.
4) The function b is invoked in function a. A new Execution Context is created. Since it sits lexically in function a, its Outer Environment is a. So when it references myVar, since myVar is not in function b's Variable Environment, it will look in function a's Variable Environment. It finds it there and console.log prints 2. But if the variable was not in function a's Variable Environment, then since function a's Outer Environment is the global Execution Context, then the Scope Chain will continue searching there.
5) After function b and a are finished execution, they are popped from the Execution Stack. The single-threaded JavaScript Engine continues execution at the global Execution Context. It invokes the b function. But there is no b function in the global Variable Environment and there is no other Outer Environment to search in the global Execution Context. Thus an exception is raised by the JavaScript Engine.
function a(){
function b(){
console.log(myVar);
}
var myVar = 2;
b();
}
var myVar = 1;
a();
b();
> 2
> Uncaught ReferenceError: b is not defined
The below example shows the Scope Chain in action. In the function b's Execution Context's Variable Environment, there is no myVar. So it searches its Outer Environment, which is the function a. The function a does not have myVar in its Variable Environment either. So the Engine searches function a's Outer Environment, which is the global Execution Context's Outer Environment and myVar is defined there. Hence, the console.log prints 1.
function a(){
function b(){
console.log(myVar);
}
b();
}
var myVar = 1;
a();
> 1
Regarding Execution Context and the Lexical Environment associated with it, including Outer Environment and Variable Environment, enable the scoping of variables in JavaScript. Even if you invoke the same function multiple times, for each invocation, it will create its own Execution Context. So each Execution Context will have its own copy of the variables in its Variable Environment. There is no sharing of variables.
function a() { } is a function statement, which creates an a variable local to the b function.
Variables are created when a function is parsed, regardless of whether the var or function statement gets executed.
a = 10 sets this local variable.
What is the bone of contention in this small snippet of code?
Case 1:
Include function a(){} definition inside the body of function b as follows. logs value of a = 1
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
console.log(a); // logs a = 1
Case 2
Exclude function a(){} definition inside the body of function b as follows. logs value of a = 10
var a = 1;
function b() {
a = 10; // overwrites the value of global 'var a'
return;
}
b();
console.log(a); // logs a = 10
Observation will help you realise that statement console.log(a) logs the following values.
Case 1 : a = 1
Case 2 : a = 10
Posits
var a has been defined and declared lexically in the global scope.
a=10 This statement is reassigning value to 10, it lexically sits inside the function b.
Explanation of both the cases
Because of function definition with name property a is same as the variable a. The variable a inside the function body b becomes a local variable. The previous line implies that the global value of a remains intact and the local value of a is updated to 10.
So, what we intend to say is that the code below
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
console.log(a); // logs a = 1
It is interpreted by the JS interpreter as follows.
var a = 1;
function b() {
function a() {}
a = 10;
return;
}
b();
console.log(a); // logs a = 1
However, when we remove the function a(){} definition, the value of 'a' declared and defined outside the function b, that value gets overwritten and it changes to 10 in case 2. The value gets overwritten because a=10 refers to the global declaration and if it were to be declared locally we must have written var a = 10;.
var a = 1;
function b() {
var a = 10; // here var a is declared and defined locally because it uses a var keyword.
return;
}
b();
console.log(a); // logs a = 1
We can clarify our doubt further by changing the name property in function a(){} definition to some other name than 'a'
var a = 1;
function b() {
a = 10; // here var a is declared and defined locally because it uses a var keyword.
return;
function foo() {}
}
b();
console.log(a); // logs a = 1
Hoisting is a concept made for us to make it easier to understand. What actually happens is the declarations are done first with respect to their scopes and the assignments will happen after that(not at the same time).
When the declarations happen, var a, then function b and inside that b scope, function a is declared.
This function a will shadow the variable a coming from the global scope.
After the declarations are done, the values assign will start, the global a will get the value 1 and the a inside function b will get 10.
when you do alert(a), it will call the actual global scope variable.
This little change to the code will make it more clear
var a = 1;
function b() {
a = 10;
return a;
function a() { }
}
alert(b());
alert(a);
It is happening because of the Variable name is same as the function name means "a".
Thus due to Javascript hoisting it try to solve the naming conflict and it will return a = 1.
I was also confused about this until i read this post on "JavaScript Hoisting" http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html
Hope it helps.
Here's my recap of the answer with more annotation and an acompaniying fiddle to play around with.
// hoisting_example.js
// top of scope ie. global var a = 1
var a = 1;
// new scope due to js' functional (not block) level scope
function b() {
a = 10; // if the function 'a' didn't exist in this scope, global a = 10
return; // the return illustrates that function 'a' is hoisted to top
function a(){}; // 'a' will be hoisted to top as var a = function(){};
}
// exec 'b' and you would expect to see a = 10 in subsequent alert
// but the interpreter acutally 'hoisted' the function 'a' within 'b'
// and in doing so, created a new named variable 'a'
// which is a function within b's scope
b();
// a will alert 1, see comment above
alert(a);
https://jsfiddle.net/adjavaherian/fffpxjx7/
scpope & closure & hoisting (var/function)
scpope : the global var can be access in any place(the whole file
scope), local var only can be accessed by the local
scope(function/block scope)!
Note: if a local variable not using
var keywords in a function, it will become a global variable!
closure : a function inner the other function, which can access
local scope(parent function) & global scope, howerver it's vars
can't be accessed by others! unless, your return it as return value!
hoisting : move all declare/undeclare vars/function to the scope
top, than assign the value or null!
Note: it just move the declare,not move the value!
var a = 1;
//"a" is global scope
function b() {
var a = function () {};
//"a" is local scope
var x = 12;
//"x" is local scope
a = 10;
//global variable "a" was overwrited by the local variable "a"
console.log("local a =" + a);
return console.log("local x = " + x);
}
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x =
console.log(x);
// ReferenceError: x is not defined
Hoisting In JavaScript means, variable declarations are executed through out the program before any code is executed. Therefore declaring a variable anywhere in the code is equivalent to declaring it at the beginning.
Its all depends on the scope of variable 'a'. Let me explain by creating scopes as images.
Here JavaScript will create 3 scopes.
i) Global scope.
ii) Function b() scope.
iii) Function a() scope.
Its clear when you call 'alert' method scope belongs to Global that time, so it will pick value of variable 'a' from Global scope only that is 1.
Long Post!
But it will clear the air!
The way Java Script works is that it involves a two step process:
Compilation(so to speak) - This step registers variables and function declarations and their respective scope. It does not involve evaluating function expression: var a = function(){} or variable expression (like assigning 3 to x in case of var x =3; which is nothing but the evaluation of R.H.S part.)
Interpreter: This is the execution/evaluation part.
Check the output of below code to get an understanding:
//b() can be called here!
//c() cannot be called.
console.log("a is " + a);
console.log("b is " + b);
console.log("c is " + c);
var a = 1;
console.log("Now, a is " + a);
var c = function() {};
console.log("Now c is " + c);
function b() {
//cannot write the below line:
//console.log(e);
//since e is not declared.
e = 10; //Java script interpreter after traversing from this function scope chain to global scope, is unable to find this variable and eventually initialises it with value 10 in global scope.
console.log("e is " + e) // works!
console.log("f is " + f);
var f = 7;
console.log("Now f is " + f);
console.log("d is " + d);
return;
function d() {}
}
b();
console.log(a);
Lets break it:
In the compilation phase,
'a' would be registered under global scope with value 'undefined'.
Same goes for 'c', its value at this moment would be 'undefined' and not the 'function()'.
'b' would be registered as a function in the global scope.
Inside b's scope, 'f' would be registered as a variable which would be undefined at this moment and function 'd' would be registered.
When interpreter runs, declared variables and function() (and not expressions) can be accessed before the interpreter reaches the actual expression line. So, variables would be printed 'undefined' and declared anonymous function can be called earlier. However, trying to access undeclared variable before its expression initialisation would result in an error like:
console.log(e)
e = 3;
Now, what happens when you have variable and function declaration with same name.
Answer is - functions are always hoisted before and if the same name variable is declared, it is treated as duplicate and ignored. Remember, order does not matter. Functions are always given precedence. But during evaluation phase you can change the variable reference to anything (It stores whatever was the last assignment) Have a look at the below code:
var a = 1;
console.log("a is " + a);
function b() {
console.log("a inside the function b is " + a); //interpreter finds 'a' as function() in current scope. No need to go outside the scope to find 'a'.
a = 3; //a changed
console.log("Now a is " + a);
return;
function a() {}
}
var a; //treated as duplicate and ignored.
b();
console.log("a is still " + a + " in global scope"); //This is global scope a.
Hoisting is behavioural concept of JavaScript. Hoisting (say moving) is concept that explains how and where variables should be declared.
In JavaScript, a variable can be declared after it has been used because Function declarations and variable declarations are always moved (“hoisted”) invisibly to the top of their containing scope by the JavaScript interpreter.
We encounter two types of hoisting in most cases.
1.Variable declaration hoisting
Lets understand this by this piece of code.
a = 5; // Assign 5 to a
elem = document.getElementById("demo"); // Find an element
elem.innerHTML = a; // Display a in the element
var a; // Declare a
//output-> 5
Here declaration of variable a will be hosted to top invisibly by the javascript interpreter at the time of compilation. So we were able to get value of a. But this approach of declaration of variables is not recommended as we should declare variables to top already like this.
var a = 5; // Assign and declare 5 to a
elem = document.getElementById("demo"); // Find an element
elem.innerHTML = a; // Display a in the element
// output -> 5
consider another example.
function foo() {
console.log(x)
var x = 1;
}
is actually interpreted like this:
function foo() {
var x;
console.log(x)
x = 1;
}
In this case x will be undefined
It does not matter if the code has executed which contains the declaration of variable. Consider this example.
function foo() {
if (false) {
var a = 1;
}
return;
var b = 1;
}
This function turns out to be like this.
function foo() {
var a, b;
if (false) {
a = 1;
}
return;
b = 1;
}
In variable declaration only variable definition hoists, not the assignment.
Function declaration hoisting
Unlike the variable hoisting the function body or assigned value will also be hoisted. Consider this code
function demo() {
foo(); // this will give error because it is variable hoisting
bar(); // "this will run!" as it is function hoisting
var foo = function () {
alert("this would not run!!");
}
function bar() {
alert("this will run!!");
}
}
demo();
Now as we understood both variable and function hoisting, let's understand this code now.
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
This code will turn out to be like this.
var a = 1; //defines "a" in global scope
function b() {
var a = function () {}; //defines "a" in local scope
a = 10; //overwrites local variable "a"
return;
}
b();
alert(a);
The function a() will have local scope inside b(). a() will be moved to top while interpreting the code with its definition (only in case of function hoisting) so a now will have local scope and therefore will not affect the global scope of a while having its own scope inside function b().
From my piece of knowledge, hoisting happens with the variable declaration and function declaration, for example:
a = 7;
var a;
console.log(a)
What happens inside JavaScript's engine:
var a;
a = 7;
console.log(a);
// 7
Or:
console.log(square(7)); // Output: 49
function square(n) { return n * n; }
It will become:
function square(n) { return n * n; }
console.log(square(7)); // 49
But assignments such as variable assigment, function expression assignment will not be hoisted:
For example:
console.log(x);
var x = 7; // undefined
It may become like this:
var x;
console.log(x); // undefined
x = 7;
To describe hosting in javascript in one sentence is variables and functions are hoisted to the top of the scope that they are declared in.
I am assuming you are a beginner, to understand hoisting properly at first we have understood the difference between undefined and ReferenceError
var v;
console.log(v);
console.log(abc);
/*
The output of the above codes are:
undefined
ReferenceError: abc is not defined*/
now in the bellow code what we see? a variable and a function expression is decleard.
<script>
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
</script>
but the real picture with proof that the both variable and function are hoisted on the top of there scope:
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));
Output of first two logs are undefined and TypeError: getSum is not a function because both var totalAmo and getSum are hoisted on the top of their scope like bellow
<script>
var totalAmo;
var getSum;
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));
</script>
But for functions declaration whole functions hoisted on the top of their scope.
console.log(getId());
function getId(){
return 739373;
}
/* output: 739373, because the whole function hoisted on the top of the scope.*/
Now the same logic goes for those varibale, functions experessions and function declaratoins declared inside functional scope. Key point: they will not be hoisted on the top of the file;
function functionScope(){
var totalAmo;
var getSum;
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
}
So, when you use var keyword, variable and function hoisted on the top of there scope (global scope and function scope).
What about let and const, const and let are still both aware of the global scope and function scope just like var is, but const and let variables are also aware of another scope called blocked scope. a block scope is present whenever there is a block of code, such as for loop, if else statement, while loop etc.
When we use const and let to declare a variable in these block scope, the variable declaration only will be hoisted on the top of that block that it is in, and it will not be hoisted on the top of the parent function or top of the global scope that it is hoisted.
function getTotal(){
let total=0;
for(var i = 0; i<10; i++){
let valueToAdd = i;
var multiplier = 2;
total += valueToAdd*multiplier;
}
return total;
}
Variables in abobe example will be hoisted like bellow
function getTotal(){
let total;
var multiplier;
total = 0;
for(var i = 0; i<10; i++){
let valueToAdd;
valueToAdd = i;
multiplier = 2;
total += valueToAdd*multiplier;
}
return total;
}
ES5: function hoisting & variable hoisting
function hoisting priority is greater than variable hoisting
"use strict";
/**
*
* #author xgqfrms
* #license MIT
* #copyright xgqfrms
* #created 2016-06-01
* #modified
*
* #description function-hoisting.js
* #augments
* #example
* #link
*
*/
(function() {
const log = console.log;
var a = 1;
function b() {
a = 10;
log(`local a`, a)
return;
// function hoisting priority is greater than variable hoisting
function a() {}
}
b();
log(`global a`, a);
// local a 10
// global a 1
})();
which is equal to
(function() {
const log = console.log;
// define "a" in global scope
var a = 1;
function b() {
// define "a" in local scope
var a ;
// assign function to a
a = function () {};
// overwrites local variable "a"
a = 10;
log(`local a`, a);
return;
}
b();
// log global variable "a"
log(`global a`, a);
// local a 10
// global a 1
})();
the reason behind of hoisting
var a = 1;
//"a" is global scope
function b() {
var a = function () {};
//"a" is local scope
var x = 12;
//"x" is local scope
a = 10;
//global variable "a" was overwrited by the local variable "a"
console.log("local a =" + a);
return console.log("local x = " + x);
}
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x =
console.log(x);
// ReferenceError: x is not defined
/**
* scpope & closure & hoisting (var/function)
*
* 1. scpope : the global var can be access in any place(the whole file scope), local var only can be accessed by the local scope(function/block scope)!
* Note: if a local variable not using var keywords in a function, it will become a global variable!
*
* 2. closure : a function inner the other function, which can access local scope(parent function) & global scope, howerver it's vars can't be accessed by others! unless, your return it as return value!
*
* 3. hoisting : move all declare/undeclare vars/function to the scope top, than assign the value or null!
* Note: it just move the declare, not move the value!
*
*/
ES6 let, const no exist hoisting
(() => {
const log = console.log;
log(a)
// Error: Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 1;
})();
(() => {
const log = console.log;
log(b)
// Error: Uncaught ReferenceError: Cannot access 'b' before initialization
const b = 1;
})();
refs
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const