4 More JavaScript Concepts That Every Developer Should Know
In my previous post I discussed four essential JavaScript concepts to master as a web developer, which I will link below —
In this next installment I will cover the next four critical concepts to grasp.
1. Callbacks
A callbacks in JavaScript is a function that is passed to another function as a parameter and are executed or invoked within that other function. The function needs to wait for another function to execute or return a value, causing a chain of functionalities to form — as JavaScript is inherently asynchronous, callbacks are employed to create a synchronous operation.
const sayHello = (greeting) => {
console.log(greeting + '' + 'Earthling');
}const greet = (callback) => {
greeting = "Bonjour";
callback(greeting);
}greet(sayHello);//Bonjour Earthling
Above, the function sayHello is passed as the callback argument to the greet function. Before sayHello is executed it waits for greet to execute.
2. Promises
According to developer.mozilla —
“A Promise is an object representing the eventual completion or failure of an asynchronous operation. Essentially, a promise is a returned object to which you attach callbacks, instead of passing callbacks into a function.”
So, the Promise object represents the success of failure of an asynchronous operation as well as its resulting value.
Promises are used to avoid getting stuck in callbacks within callbacks (and so on…). Having a callback within a callback falls in to the realm of recursion, but without the assistance of Promises you can easily get stuck in a neverending cycle. Promises are most useful when your asynchronous operations when it contains two or more back to back operations (aka a chaining callback). A Promise may come in three different states — fulfilled, rejected, and pending. Fulfilled is returned when an operation is successfully completed. Rejected is when the opertion has failed. Pending is when the initial state is returned, neither fulfilled nor rejected.
The syntax for creating a Promise is as follows —
const promise = new Promise((resolve, reject) => {
isMine = true;
if(isMine) {
resolve("This cat is mine")
} else {
reject("This cat is not mine")
}promise.then(result => console.log(result))
.catch(() => {
console.log('error!')
)}//This cat is mine
//Promise {<resolved>: undefined}
3. Async & Await
Similar to Promises, Async and Await provide a means for maintaining asynchronous operations in a more synchronous manner. They are syntactic sugar on top of Promises.
Async & Await can be used within a REST API request where you want the data to fully load before it is displayed to the user.
const displayPeople = async () => {
const response = await fetch('https://example.com/people');
const people = await response.json();console.log(people);
}
displayPeople();//
In order for JavaScript to know that we are working with Promises, our ‘await’ code needs to be wrapped in an ‘async’ function. Above, we are awaiting two things — response and people. Prior to converting the response to JSON, it must be confirmed that the response has been fetched — if the response is not yet present, trying to convert to JSON will results in an error (thus await).
4. LIFO in the Call Stack
In order to manage execution contexts (Global Execution Context and Function Execution Context), JavaScript employs a call stack. This call stack utilizes the concept of LIFO — Last In First Out. When executing a script, JavaScript creates a Global Execution Context and pushes it to the top of the call stack.
Every time that a function is called, JavaScript creates a Function Execution Context for the function, pushes this function to the top of the call stack and begins executing the function.
When a functions calls another function, JavaScript creates a new Function Execution Context for this function and pushes it to the top of the call stack. When the current function is resolved it is popped off the call stack and execution is resumed where it left off. The script will conclude when the call stack is empty.