Comprehensive Guide to JavaScript - Part 5 - Advanced Concepts
Tags: webdev, javascript, beginners
Published: 2020-07-06 12:08:38

## **Execution Context**

When the javascript engine reads our code:
1. Before executing anything, the global execution context is created which is the global environment(browser window).
2. Any function executed creates a new execution context and this gets added to the call-stack.

#### Call Stack

The Call Stack is a data structure that contains information about the order of execution of function calls.

Example:
```javascript
function Function1() {
    Function2();
}

function Function2() {
    throw new Error("Something went wrong!") 
}

Function1();
```
Call-Stack:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1ncmkzs0iw0yazq2lliz.jpg)

## **DOM Manipulation**

DOM (Document Object Model) is something that is created by the browser when a web page is loaded. Go to your browser console and enter to see all the elements on your webpage.
```javascript
console.log(document);
```
Now let's manipulate this document by creating an object:
```javascript
var Obj = document.createElement("div");
console.log(Obj);
```
You can also add text inside the div. Create a div in the HTML file and assign an id to it as *test*. Then we manipulate the text inside the div:
```javascript
var Obj = document.getElementById("test");
Obj.innerText = "DEV is the best!";
```
Now create a p tag in the HTML file and give it an id of *test1* and add some contents. Now let's try and manipulate its style using javascript:
```javascript
var para = document.querySelector("p");
para.style.fontSize = "25px";
para.style.color = "red";
```

There are many more such DOM Manipulation methods which you can learn about [here](https://www.impressivewebs.com/10-essential-dom-methods-techniques-for-practical-javascript/).

## **Prototypes and Inheritance**

#### Prototypes

In my previous article in the series, I had mentioned that almost everything in javascript is an object. Each object has a special private property which has a link to another object called its prototype. For Example:
```javascript
const myCar = {
    name: "Lamborghini",
    model: "Aventador"
}
```
Running the below command:
```javascript
console.log(myCar.name);
```
retrieves the name property of the myCar object. Now what if we printed something that doesn't exist in the object. Like:
```javascript
console.log(myCar.color);
```
it returns *undefined*. But if we type in:
```javascript
console.log(myCar.toString());
```
returns a String.
It's a bit tricky. Hope you understood what happened there. Just type in:
```javascript
console.log(Object.prototype);
```
to get the list of all available prototypes on an object. Similarly, enter the command below to get all array prototypes.
```javascript
console.log(Array.prototype);
```

#### **Inheritance**

* Objects
```javascript
const Student = {
    admitted: true,
}

const John = Object.create(Student);
console.log(John);
```
The above piece of code created an object called John which inherited properties of Student object.

* Class
```javascript
class Student {
   constructor(name, age) {
      this.name = name;
      this.age = age;
   }
}
class Boy extends Student {
   constructor(name, age, grade) {
      super(name, age); // super class Student constructor
      this.grade = grade;
   }
}
const obj = new Boy("John", 15, 9);
console.log(obj.name); // John
```
This code has a class called Boy which inherits from Student which is its superclass and calls its constructor upon instantiating an object.

## **Call, Apply, Bind**

These are some of the important methods that are called on functions. These are designed to set the context(this).

#### call()

This function is used by an object to use a method belonging to another object.
```javascript
var Car = {
   fullName: function() {
      return this.firstName + " " + this.lastName; 
   }
}
var car1 = {
   firstName: "Lamborghini",
   lastName: "Aventador"
}
console.log(Car.fullName.call(car1)); // returns Lamborghini Aventador
```

#### apply()

This is similar to call() and useful when arguments are in the form of an array.
```javascript
var Car = {
   fullname: function(color, speed) {
      return this.firstName + " " + this.lastName + " with color " + color + " and top speed of " + speed; 
   }
}
var car1 = {
   firstName: "Lamborghini",
   lastName: "Aventador"
}
console.log(Car.fullName.apply(car1, ["orange", "349"])); // returns Lamborghini Aventador with color orange and top speed of 349
```

#### bind()

Returns a new function when called and has its *this* set to a specific value.
```javascript
var car1 = {
   firstName: "Lamborghini",
   lastName: "Aventador"
}

var fullname = function(color, speed) {
   return this.firstName + " " + this.lastName + " with color " + color + " and top speed of " + speed; 
}

var binding = fullname.bind(car1);
console.log(binding("red", "349")); // Lamborghini Aventador with color red and top speed of 349
```

## **IIFE**

IIFE(Immediately Invoked Function Expression) are functions that are executed as soon as they are created. They are used to avoid changing the global variables in the program.
```javascript
(function() {
   console.log("Dev is amazing!");
})(); // returns Dev is amazing
```

## **Synchronous and Asynchronous Function**

JavaScript is synchronous and executes code line by line. To demonstrate this have a look at the piece of code below:
```javascript
function f1() {
   console.log("I am function 1");
}
function f2() {
   console.log("I am function 2");
}
f1(); // returns I am function 1
f2(); // returns I am function 2
```
This means that javascript executes function f1 completely and then moves onto the next function f2.
What if there were complex operations that are taking place in f1 and f2 has to wait a long time for f1 to finish? This is where javascript's asynchronous operations come in handy. For example:
```javascript
function f1() {
   console.log("I am function 1");
}
function looper() {
   setTimeout(function() {
      for(let i=0; i<99999; i++) {}
      console.log(i);
   }, 1000);
}
function f2() {
   console.log("I am function 2");
}
f1();
looper();
f2();
```
Although looper is called before f2, the output's first line prints *I am function 1*, followed by *I am function 2*, then the looper function is executed. We have achieved asynchronous property of javascript here.

## **Callbacks and Higher Order Functions**

#### Callbacks Functions

A function passed in to another function is called a callback. JavaScript objects are first-class objects i.e. we can pass a function as an argument to another function.
```javascript
setTimeout(function() {
   console.log("Hello There!");
}, 5000); // prints "Hello There" after 5 seconds
```

#### Higher Order Functions

A function that takes another function as an argument and returns it. Functions such as map(), reduce(), filter(), sort(), etc. are called higher-order functions in javascript. These functions have been discussed in my [previous article](https://dev.to/kgprajwal/a-comprehensive-guide-to-javascript-part-4-arrays-488f).

## **Strict Mode**

Strict mode enables a 'strict' operating context and prevents certain actions and throws exceptions more often. Strict mode helps in writing better code and prevents the use of an undeclared variable. For example:
```javascript
x = 50;
console.log(x); // prints 50
```
This will normally execute and won't throw any error. But in production, this might cause serious issues. Hence, strict mode helps in this case:
```javascript
"use strict";
x = 50;
console.log(x);
```
Executing the above piece of code will throw errors as x is undeclared. There are other kinds of stuff which aren't allowed in a strict mode such as:
- Restrict the use of an undeclared variable.
- Deleting a variable or function.
- Duplication of the parameter name.
- Octal numeric literals not allowed.
- Writing read-only and get-only property is not allowed.
- Escape characters can't be used.

## **Promise**

A promise is an object and is an assurance for resolving something that is to happen in the future else it is rejection. A promise has three states namely:
- Resolve: Completed
- Reject: Failed
- Pending: State between success or failure of the promise
When data is requested from the server, it is in pending state. If the data is successfully retrieved from the server the promise is said to be resolved. If the information isn't fetched it results in a rejection. For Example:
```javascript
f1()
  .then(function(response) {
    return f2(response);
}).then(function(nextResponse) {  
    return f3(nextResponse);
}).then(function(result) {  
    console.log(result);
}).catch(rejection);
```
The above code demonstrates how promises can be chained together and make each promise dependent on the previous one. This is achieved using then(), which depicts the action to be performed upon resolving the promise.

## **Async/Await**

Async/Await is a type of promise. Probably the most popular and most used one. We declare an async function and await for the promise to resolve before printing a message.
```javascript
async function hello() {
  return greeting = await Promise.resolve("Hello");
};

hello().then(alert);
```

These were some of the advanced topics in javascript. I hope I delivered them well.

***Thank You!***