About the series
Core JavaScript is a series I'm writing that covers, as the name suggests, some of the core principles of JavaScript. It originally started as a study or reference material for myself, but I decided to share it with the community in the hopes that it will prove useful for others.
This series is intended for beginner JavaScript developers or more experienced developers in need of a refresher. I have a few topics planned out already, but I would love to hear from you if there are any topics, in particular, you would be interested to read about!
You might recall that in a previous article we came across the concept of hoisting in JavaScript. Essentially, hoisting is the process through which the declaration of a variable or function is moved to the top of its scope. It allows us to use variables and call functions before they appear in our code.
Declaration vs Assignment / Initialization
It is important to note that only declarations are hoisted, and initializations and assignments are not. Below is the difference, in case you need a refresher.
let number; // Declaration
number = 5; // Assignment
const name = 'John'; // Initialization
Consider the following examples:
var first = 1;
var second = 2;
console.log(first + " " + second); // Output: 1 2
var first = 1;
console.log(first + " " + second) // Output: 1 undefined
var second = 2;
Because declarations are hoisted to the top of the scope but initializations are not, the second example essentially gets translated to the following:
var first = 1;
var second; // This is currently undefined
console.log(first + " " + second) // Output: 1 undefined
second = 2;
Var vs Let vs Const
If you've read my previous article about variable types, you know that var
variables are hoisted to the top of their scope and initialized with the value of undefined
. Some consider let
and const
to be non-hoisted, which is not entirely correct. In reality, let
and const
variables are indeed hoisted to the top of their scope, but they are not initialized.
This means that with var
we can do something like this:
console.log(number); // undefined
var number = 5;
However, trying to do the same thing with let
or const
will throw an error:
console.log(number); // ReferenceError: number is not defined
let number = 5;
Functions
Hoisting works the same for functions as it does for variables - function declarations are hoisted, but function expressions are not.
hoistedFunction();
function hoistedFunction() { // Function declaration
console.log('This will work!');
}
// Output: This will work!
nonHoistedFunction();
let nonHoistedFunction = () => { // Function expression
console.log('This will not work...');
}
// Output: ReferenceError: nonHoistedFunction is not defined
If we use var
instead of let
, we still get an error, but of a different kind.
nonHoistedFunction();
var nonHoistedFunction = () => { // Function expression
console.log('This will still not work...');
}
// Output: TypeError: nonHoistedFunction is not a function
Tip - Declare variables at the top
Hoisting is easy to forget about or overlook, which tends to lead to bugs and confusion. Declaring variables at the top of their scope helps you avoid errors and it keeps your code clean.
Practice
What are the outputs of these code snippets?
example(); function example() { let name = 'Bon Jovi'; console.log(name); }
Answer:
Bon Jovi
Reason:
example()
is a function declaration, which is hoisted - therefore, it can be called before it appears in our code and everything will work as intended.example(); function example() { console.log(name); let name = 'Bon Jovi'; }
Answer:
ReferenceError: Cannot access 'name' before initialization
Reason:
let
variables, despite being hoisted to the top of their scope, are not initialized. Therefore, we are warned that we cannot usename
before it is initialized.example(); let example = () => { let name; console.log(name); name = 'Bon Jovi'; }
Answer:
ReferenceError: example is not defined
Reason: Function expressions are not hoisted, therefore we cannot use them before they appear in the code. Because we are using
let
here, we get a ReferenceError.
Thank you for reading the third article in my Core JavaScript series! If you found this useful, if you have anything to add, or if I made any mistakes - I would love to hear from you! I'm also very open to suggestions for future topics for the series. 😊
Expect to see the next part soon. Thanks and see you there!