![]()
Hoisting by the JS Engine makes some variables available for use before they are declared by the JS engine creating a "variable environment object" as the code is initially scanned before being run.
It is best to experiment with the various variable type to understand which get hoisted and which don't, as behaviour varies markedly.
| HOISTED? | Initial Value | scope |
| Function declarations | Yes | Actual function | block |
| var | Yes | undefined | function |
| Let/const | Not in practice, technically Yes | Uninitialized,
Temporal Dead Zone |
block |
| Func expressions/Arrows | Depends if var or let/const used |
// Temporal Dead Zone, Let and Const: Function Declarations (function blah = {} etc) are hoisted
const myName = 'Jonas'
// var "job" is defined but inaccesible - and VS code does not highlight ${} as a var either
if (myName === 'Jonas') {
// -------------TDZ for job var-----------
console.log(`${job}`);
const job = "teacher"
// Uncaught ReferenceError: Cannot access 'job' before initialization - because of unhoisted variable const - if lines are reversed (Alt ^ arrow) then it works. Initially it is treated as not existing
// const age = 2037 - 1989
// console.log(age);
// 48
//--------------TDZ for job var-----------
//
//-------------x is in TDZ until initialised _________
// console.log(x)
// Uncaught ReferenceError: x is not defined yet - it is in TDZ as uninitialized from JS initial code scan, so it is expected to be defined at some future point
//-------------x is in TDZ until initialised _________
So what is and why a TDZ? It was created in the JS Engine so that variables would not be accessible before they are declared to prevent bugs, bad programming practises and catch errors. So the JS engine in the browser F12 console flags an error and prevents continuation of the running code until fixed.
It also makes const variables constant! They cannot be re-assigned later, else flag an error, unlike "let", partly.
// basic assignment behaviour: let a = 1 a = 2 // no prob so far...! // let a = 3 // Identifier 'a' has already been declared const b = 2 // b = 3 // Uncaught TypeError: Assignment to constant variable. var c = 1 c = 2 var c = 3 // no probs at all!! var is a wildcard that allows re-assignment at any point so makes keeping track of a var difficult across all scopes, whether global, local, functional or block scopes. It should not be used, but will exist in older code.
Hoisting was created to make certain programming requirements possible even if it causes some confusion, a by product of which was the neccesity for var also being hoisted (and now still allowed to be defined as "undefined" instead of uninitialised, if not declared - a bad idea) in older versions of JS, which is why var should not be used any more, but let or const instead. The original JS design never intended or foresaw JS being used as it is now as such a powerful manipulator of CSS and HTML, due to Internet requirements.
// console.log(me); // hoisted ok but undefined yet // undefined // console.log(job); // in TDZ here // Uncaught ReferenceError: Cannot access 'job' before initialization // console.log(year); // in TDZ here // Uncaught ReferenceError: Cannot access 'year' before initialization // The let and const issues can be fixed by reversing their Top To Bottom order of being called // var me = "Fred" // let job = "teacher" // const year = 1992
So how does function hoisting behave?
// Hoisting functions - declaration, expression and arrow: console.log(addDecl(2,3)); // 5 // declaration hoisted ok function addDecl(a,b) { return a + b } // console.log(addExpr(2,3)); // Uncaught ReferenceError: Cannot access 'addExpr' before initialization const addExpr = function (a,b) { return a +b } As with the variables defined by const and let above before, const functions are in the TDZ until their Top To Bottom order has changed places console.log(addArrow(2,3)); // Uncaught ReferenceError: Cannot access 'addArrow' before initialization const addArrow = (a,b) => a + b As with the variables defined by const and let above before, const functions are in the TDZ until their Top To Bottom order has changed places
// console.log(addExpr); // undefined // but if arguments are given: // console.log(addExpr(1,2)); // Uncaught TypeError: addExpr is not a function. This is because it is like using; // console.log(undefined(1,2)); // Uncaught TypeError: undefined is not a function var addExpr = function (a, b) { return a + b; }; // Obviously, the same applies to an Arrow func console.log(addArrow(1,2)); // Uncaught ReferenceError: Cannot access 'addArrow' before initialization let addArrow = (a, b) => a + b;
SUMMARY: ONLY function Declarations are hoisted by the JS Engine so work, no matter where - above or below each other - in the code the variable or declaration is placed.