Hoisting
Hoisting means lifting.
It was actually created to simplify(wait, what?) Javascript originally, by avoiding referencing error. After hoisting, we can use a variable before it's declared (unlike Java).
1. Definition and Example
function test() {
console.log(val); // ?
console.log(foo()); // ?
var val = 1;
function foo() {
return 2;
}
}
test();
Here's what actually happened:
function test() {
// a variable declaration will only be hoisted to it's own scope's top
var val = undefined;
function foo() {
return 2;
}
console.log(val); // val was lifted but is init as undefined
console.log(foo()); // foo() was lifted
val = 1;
}
test();
The behavior that Javascript Interpreter (such as Google V8) hoists/lifts the declaration part up to the scope's top is called hoisting
.
2. Types of Hoisting
1. Declare + Assign:
- variables:
var val = 10
. - functions:
var foo = function() {...}
For these forms, only the left/declaration part will be hoisted. As var val = undefined
, var foo = undefined
will be lifted to top.
test() {
...
var val = 100;
var foo = function() {...};
}
// Becomes:
test() {
var val = undefined;
var foo = undefined;
...
val = 100;
foo = function() {...};
}
2. Declare-only:
For functions declared as function foo() {...};
will be fully lifted to the top of the scope.
test() {
var foo = 2;
...
function foo() {...};
}
// Becomes:
test() {
var foo;
function foo() {...};
// all declarations are on top
foo = 2;
...
}
2. With ES6
function test() {
console.log(val);
let val = 1;
}
test();
We got an error says: Uncaught ReferenceError: val is not defined
. This is because let
and const
will not be hoisted.
3. A Little Bit More Complex (Ref.1):
var num = 1;
function() {
if (!num) {
var num = 100;
}
console.log(num);
}
Answer is 100. Why? Here's what actually happens:
var num = 1;
function() {
var num = undefined;
if (!num) { // true
var num = 100;
}
console.log(num);
}
Remember declaration will be hoisted to top of it's scope. And if
doesn't create new scope for var
.
What about we use const?
const num = 1;
function() {
if (!num) {
const num = 100;
}
console.log(num);
}
Will get error: Uncaught TypeError: Identifier 'num' has already been declared
. Because:
const
will not be hoisted, thus we will get intoif
.- Then we are trying to declare
num
again withconst
, which is not allowed.
References:
- JS: Explain “hoisting”: http://lucybain.com/blog/2014/hoisting/