I believe that one of the first and foremost reasons people struggle to understand hoisting is because the term itself is somewhat misleading. The Merriam-Webster definition of the word hoist is "an act of raising or lifting".
This might lead one to assume that hoisting involves written code being physically rearranged somehow. This is not true.
Typically, hoisting is described as the moving of variable and function declarations to the top of their (global or function) scope.
However, the variables do not move at all.
What actually happens is that during the compilation phase declared variables and functions are stored in memory before the rest of your code is read, thus the illusion of "moving" to the top of their scope.
After the first phase has finished and all the declared variables have been hoisted, the second phase begins; execution. The interpreter goes back up to the first line of code and works its way down again, this time assigning variables values and processing functions.
Yes, variables declared with let and const are hoisted. Where they differ from other declarations in the hoisting process is in their initialization.
console.log(name); // undefined
var name = "Andrew";
Contrastingly, variables declared with let, const, and class are hoisted but remain uninitialized:
console.log(name); // Uncaught ReferenceError: name is not defined
let name = "Andrew";
These variable declarations only become initialized when they are evaluated during runtime. The time between these variables being declared and being evaluated is referred to as the temporal dead zone. If you try to access these variables within this dead zone, you will get the reference error above.
Because the variable has not been initialized, it has not been assigned a value, and thus the reference error is returned stating that name is not defined.
It's not an error to reference let and const variables in code above their declaration as long as that code is not executed before their declaration.
For example, this code works fine:
However, this will result in a reference error:
This error is generated because greetings() was executed before the variable name was declared.