Javascript function scoping and hoisting
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"
How does this hoisting work with block scope?
According to the web compat semantics at the place of the function declaration, the value of the blocked scope variable is bound to the outer scope². This code is equivalent to:
let outerFoo; // the functions create a binding outside of the scope
{
let innerFoo; // but also inside
// due to hoisting, functions get bound before any code get's executed:
innerFoo = function foo() {
console.log('A');
};
innerFoo = function foo() {
console.log('B');
};
// At the place of the function declaration, the variable leaves the scope
/* function foo() {
console.log('A');
} */
outerFoo = innerFoo;
innerFoo();
innerFoo = 1;
// this also applies to the second declaration
/* function foo() {
console.log('B');
} */
outerFoo = innerFoo;
innerFoo = 2;
console.log(innerFoo);
}
console.log(outerFoo);
How JS hoisting works within functions?
JavaScript hoisting within functions means that the declaration of variables are moved to the top of the function block. When you enter foo()
, var boo
is redeclared instantly even though you have not reached it (because the JS engine knows that this declaration exists within the function). Accordingly, the reason that it is undefined is because it has only been declared, you don't assign a value until the following line.
In reality, this is not a situation you should find yourself in if you declare variables in an appropriate scope and don't redeclare variables with the same name, but I understand your curiosity.
You can read more about this here.
JavaScript 'hoisting'
- The global
a
is set to1
b()
is calledfunction a() {}
is hoisted and creates a local variablea
that masks the globala
- The local
a
is set to10
(overwriting the functiona
) - The global
a
(still1
) is alerted
Hoisting and variable scope
Variable declarations hoist to the top of the execution context, in this case the function users. Rewriting these to show how it looks from the hoisted perspective often clears up any confusion
var name = "Paul";
function users () {
var name;//<- hoisted variable declaration
if (!name) {
name = "Jack";
}
console.log(name);
}
users(); //outputs "Jack"
vs.
var name = "Paul";
function users () {
if (!name) {//no hoisted variable declaration, uses global
name = "Jack";
}
console.log(name);
}
users(); //outputs "Paul"
Execution contexts contain several key components, the most relevant here are the lexical environment and variable environment. I cover the differences between the two (and some brief history) in more depth if you are interested here: https://stackoverflow.com/a/32573386/1026459
Related Topics
Can a Website Detect When You Are Using Selenium With Chromedriver
Create and Save a File With JavaScript
Updating a Nested Array With Mongodb
How to Clone an Array of Objects in JavaScript
What Does [Object Object] Mean
Parse Query String in JavaScript
Convert Js Object to Json String
Safely Turning a Json String into an Object
How to Convert a String to an Integer in JavaScript
How to Do String Interpolation in JavaScript
How to Use Unicode-Aware Regular Expressions in JavaScript
Get the Current Url With JavaScript
What Is Spreadelement in Ecmascript Documentation? Is It the Same as Spread Syntax At Mdn