# Graph Data Structures in JavaScript for Beginners Graph Data Structures in JavaScript for Beginners - In this post, we are going to explore non-linear data structures like graphs. Also, we’ll cover the central concepts and typical applications.

Graph Data Structures in JavaScript for Beginners - In this post, we are going to explore non-linear data structures like graphs. Also, we’ll cover the central concepts and typical applications.

You are probably using programs with graphs and trees. Let’s say for instance that you want to know the shortest path between your workplace and home, you can use graph algorithms to get the answer! We are going to look into this and other fun challenges.

In the previous post, we explore linear data structures like arrays, linked lists, sets, stacks and so on. This one builds on top of what we learned.

You can find all these implementations and more in the Github repo:https://github.com/amejiarosario/dsa.js

Here is the summary of the operations that we are going to cover on this post:

1. Graphs Basics

Before we dive into interesting graph algorithms, let’s first clarify the naming conventions and graph properties.

A graph is a data structure where a node can have zero or more adjacent elements.

The connection between two nodes is called edge. Nodes can also be called vertices.

The degree is the number of edges connected to a vertex. E.g., the `purple` vertex has a degree of 3 while the `blue` one has a degree of 1.

If the edges are bi-directional, then we have an undirected graph. But, if the edges have a direction, then we have a directed graph or di-graph for short. You can think of it as a one-way street (directed) or two-way street (undirected).

Vertex can have edges that go to itself (e.g., `blue` node), this is called self-loop.

A graph can have cycles which means that if you traverse through the node, you could get the same node more than once. The graph without cycles is called acyclic graph.

Also, acyclic undirected graphs are called tree. We are going to cover trees in depth in the next post.

Not all vertices have to be connected in the graph. You might have isolated nodes or even separated subgraphs. If all nodes have at least one edge, then we have a connected graph. When all nodes are connected to all other nodes, then we have a complete graph.

For a complete graph, each node should have `#nodes - 1` edges. In the previous example, we have seven vertices, so each node has six edges.

2. Graph Applications

When edges have values/cost assigned to them, we say we have a weighted graph. If the weight is absent, we can assume it’s 1.

Weighted graphs have many applications depending on the domain where you need to solve a problem. To name a few:

• Airline Traffic (image above)
Node/vertex = AirportEdges = direct flights between two airportsWeight = miles between two airports* GPS Navigation
Node = road intersectionEdge = roadWeight = time required to go from one intersection to another* Networks routing
Node = serverEdge = data linkWeight = connection speed
In general, graphs have many real-world applications like:
• Electronic circuits
• Flight reservations
• Driving directions
• Telcom: Cell tower frequency planning
• Social networks. E.g., Facebook uses a graph for suggesting friends
• Recommendations: Amazon/Netflix uses graphs to make suggestions for products/movies
• Graphs help to plan the logistics of delivering goods

We just learned the basics of graphs and some applications. Let’s cover how to represent graphs in JavaScript.

3. Representing graphs

There are two primary ways of representing graph:

Let’s explain it with the following directed graph (digraph) as an example:

We digraph with 4 nodes. When a vertex has a link to itself (e.g. `a`) is called self-loop.

The adjacency matrix is one way of representing a graph using a two-dimensional array (NxN matrix). In the intersection of nodes, we add 1 (or other weight) if they are connected and `0` or `-` if they are not connected.

Using the same example as before, we can build the following adjacency matrix:

``````  a b c d e
a 1 1 - - -
b - - 1 - -
c - - - 1 -
d - 1 1 - -

``````

As you can see, the matrix list all nodes horizontally and vertically. If there a few connections we called sparse graph if there are many connections (close to the max number of links) we called it dense graph. If all possible connections are reached, then we have a complete graph.

It’s important to notice that for undirected graphs the adjacency matrix will always be symmetrical by the diagonal. However, that’s not always the case on a digraph (like our example).

What is the time complexity of finding connections of two vertices?

Querying if two nodes are connected in an adjacency matrix takes a constant time or O(1).

What is the space complexity?

Storing a graph as an adjacency matrix has a space complexity of O(n2), where `n` is the number of vertices. Also, represented as O(|V|2)

What is the runtime to add a vertex?

The vertices are stored as a `<em>V</em>`x`<em>V</em>` matrix. So, every time a vertex is added, the matrix needs to be reconstructed to a `<em>V+1</em>`x`<em>V+1</em>`.

Since the matrix has a VxV matrix, to get all the adjacent nodes to a given vertex, we would have to go to the node row and get all its edges with the other nodes.

In our previous example, let’s say we want all the adjacent nodes to `b`. We have to get the full row where b is with all the other nodes.

`````` a b c d e
b - - 1 - -

``````

We have to visit all nodes so,

Imagine that you need to represent Facebook network as a graph. You would have to create a matrix of 2 billion x 2 billion, where most of it would be empty! Nobody would know everybody else just a few thousands at most.

In general, we deal with sparse graphs so the matrix will waste a lot of space. That’s why in most implementation we would use an adjacency list rather than the matrix.

Adjacency List is one of the most common ways to represent graphs. Each node has a list of all the nodes connected to it.

Graphs can be represented as an adjacency list using an Array (or HashMap) containing the nodes. Each of these node entries includes a list (array, linked list, set, etc.) that list its adjacent nodes.

For instance, in the graph above we have that `a` has a connection to `b` and also a self-loop to itself. In turn, `b` has a connection to `c` and so on:

``````a -> { a b }
b -> { c }
c -> { d }
d -> { b c }

``````

As you can imagine if you want to know if a node is connected to another node, you would have to go through the list.

Querying if two nodes are connected in an adjacency list is O(n), where `n` is the number of vertices. Also represented as O(|V|)

Storing a graph as an adjacency list has a space complexity of O(n), where `n` is the sum of vertices and edges. Also, represented as O(|V| + |E|)## 4. Adjacency List Graph HashMap Implementation

The adjacency list is the most common way of representing graphs. There are several ways to implement the adjacency list:

One of them is using a HashMap. The `key` is the value of the node, and the `value` is an array of adjacency.

``````const graph = {
a: ['a', 'b'],
b: ['c'],
c: ['d'],
d: ['b', 'c']
}

``````

Graph usually needs the following operations:

Let’s say that we want to remove the vertex `b`. We could do `delete graph['b'];`, however, we still have to remove the references on the adjacency list on `d` and `a`.

Every time we remove a node, we would have to iterate through all the nodes’ list O(|V| + |E|). Can we do better? We will answer that soon, but first, let’s *implement our list in a more object-oriented way so we can swap implementations easily.

5. Adjacency List Graph OO Implementation

Let’s start with the `Node` class that holds the vertex’s value and its adjacent vertices. We can also have helper functions for adding and removing adjacent nodes from the list.

``````class Node {
constructor(value) {
this.value = value;
}

}

if(index > -1) {
return node;
}
}

}

}
}

``````

Notice that `adjacent` runtime is O(1), while `remove adjacent` is O(|E|). What if instead of an array use a HashSet 🧐? It could be O(1). But, let first get it working and later we can make it faster.

Make it work. Make it right. Make it faster.
Ok, now that we have the `Node` class, let’s build the Graph class that can perform operations such as adding/removing vertices and edges.

Graph.constructor

``````class Graph {
constructor(edgeDirection = Graph.DIRECTED) {
this.nodes = new Map();
this.edgeDirection = edgeDirection;
}
// ...
}

Graph.UNDIRECTED = Symbol('directed graph'); // one-way edges
Graph.DIRECTED = Symbol('undirected graph'); // two-ways edges

``````

The first thing that we need to know is if the graph is directed or undirected. That makes a difference when we are adding edges.

To add an edge we need two nodes. One is the source, and the other is the destination.

``````addEdge(source, destination) {

if(this.edgeDirection === Graph.UNDIRECTED) {
}

return [sourceNode, destinationNode];
}

``````

We add an edge from the source vertex to the destination. If we have an undirected graph, then we also add from target node to source since it’s bidirectional.

The runtime of adding an edge from a graph adjacency list is: O(1)
If we try to add an edge and the nodes don’t exist, we need to create them first. Let’s do that next!

The way we create a node is that we add it to the `this.nodes` Map. The map store a key/value pair, where the `key` is the vertex’s value while the map `value` is the instance of the node class. Take a look at line 5-6:

``````addVertex(value) {
if(this.nodes.has(value)) {
return this.nodes.get(value);
} else {
const vertex = new Node(value);
this.nodes.set(value, vertex);
return vertex;
}
}

``````

If the node already exists we don’t want to overwrite it. So, we first check if it already exists and if it doesn’t, then we create it.

The runtime of adding a vertex from a graph adjacency list is: O(1)

Graph.removeVertex

Removing a node from the graph, it’s a little bit more involved. We have to check if the node to be deleted it’s in use as an adjacent node.

``````removeVertex(value) {
const current = this.nodes.get(value);
if(current) {
for (const node of this.nodes.values()) {
}
}
return this.nodes.delete(value);
}

``````

We have to go through each vertex and then each adjacent node (edges).

The runtime of removing a vertex from a graph adjacency list is O(|V| + |E|)
Finally, let’s remove implement removing an edge!

Graph.removeEdge

Removing an edge is pretty straightforward and similar to `addEdge`.

``````removeEdge(source, destination) {
const sourceNode = this.nodes.get(source);
const destinationNode = this.nodes.get(destination);

if(sourceNode && destinationNode) {

if(this.edgeDirection === Graph.UNDIRECTED) {
}
}

return [sourceNode, destinationNode];
}

``````

The main difference between `addEdge` and `removeEdge` is that:

• If the vertices don’t exist, we won’t create them.
• We use `Node.removeAdjacent` instead of `Node.addAdjacent`.

Since `removeAdjacent` has to go through all the adjacent vertices we have the following runtime:

The runtime of removing an edge from a graph adjacency list is O(|E|)
We are going to explore how to search for values from a node.

6. Breadth-first search (BFS) - Graph search

Breadth-first search is a way to navigate a graph from an initial vertex by visiting all the adjacent nodes first.

Let’s see how we can accomplish this in code:

``````*bfs(first) {
const visited = new Map();
const visitList = new Queue();

while(!visitList.isEmpty()) {
const node = visitList.remove();
if(node && !visited.has(node)) {
yield node;
visited.set(node);
}
}
}

``````

As you can see, we are using a `Queue` where the first node in is also the first node to be visited (FIFO).

We are as well using JavaScript generators, notice the `*` in front of the function. This generator iterates one value at a time. That’s useful for large graphs (millions of nodes) because in most cases you don’t need to visit every single node.

This an example of how to use the BFS that we just created:

``````const graph = new Graph(Graph.UNDIRECTED);

bfsFromFirst = graph.bfs(first);

bfsFromFirst.next().value.value; // 1
bfsFromFirst.next().value.value; // 2
bfsFromFirst.next().value.value; // 3
bfsFromFirst.next().value.value; // 4
// ...

``````

You can find more illustrstions of usage in the test cases. Let’s move on to the DFS!

7. Depth-first search (DFS) - Graph search

Depth-first search is another way to navigate a graph from an initial vertex by recursively the first adjacent node of each vertex found.

The iterative implementation of a DFS is identical to the BFS, but instead of using a `Queue` you use a `Stack`:

``````*dfs(first) {
const visited = new Map();
const visitList = new Stack();

while(!visitList.isEmpty()) {
const node = visitList.remove();
if(node && !visited.has(node)) {
yield node;
visited.set(node);
}
}
}

``````

We can test our graph as follow.

``````const graph = new Graph(Graph.UNDIRECTED);

dfsFromFirst = graph.dfs(first);
visitedOrder = Array.from(dfsFromFirst);
const values = visitedOrder.map(node => node.value);
console.log(values); // [1, 4, 8, 3, 7, 6, 10, 2, 5, 9]

``````

As you can see the graph is the same on BFS and DFS, however, the order how the nodes were visited is very different. BFS went from 1 to 10 in that order, while DFS went as deep as it could on each node.

8. Graph Time and Space Complexity

We have seen some of the basic operations of a Graph. How to add and remove vertices and edges. Here’s a summary of what we have covered so far:

As you can see, an adjacency list is faster in almost all operations. The only action that the adjacency matrix will outperform the adjacency list is checking if a node is adjacent to other. However, if we change our implementation from Array to a HashSet, we can get it in constant time as well :)

9. Summary

As we saw, Graphs can help to model many real-life scenarios such as airports, social networks, internet and so on. We covered some of the most basic algorithms such as Breadth-First Search (BFS) and Depth-First Search (DFS). Also, we studied about implementations trade-offs such as adjacency list and matrix. Subscribe to my newsletter and don’t miss any of my posts, because there are many other applications that we are going to learn soon, such as finding the shortest path between nodes and different exciting graph algorithms!

## The API I wish JavaScript GraphQL implementations supported The API I wish JavaScript GraphQL implementations supported - The GraphQL schema language is great! It is certainly the best way to communicate anything about a GraphQL service. No wonder all documentations now use it!

The API I wish JavaScript GraphQL implementations supported - The GraphQL schema language is great! It is certainly the best way to communicate anything about a GraphQL service. No wonder all documentations now use it!

The Schema Language

Imagine that you’re building a blog app (with GraphQL) that has "Articles" and "Comments" . You can start thinking about its API schema by basing it on what you plan for its UI. For example, the main page will probably have a list of articles and an item on that list might display a title, subtitle, author’s name, publishing date, length (in reading minutes), and a featured image. A simplified version of Medium itself if you may:

We can use the schema-language to plan what you need so far for that main page. A basic schema might look like:

``````type Query {
articleList: [Article!]!
}
type Article {
id: ID!
title: String!
subTitle: String
featuredImageUrl: String
publishedAt: String!
author: Author!
}
type Author {
name: String!
}

``````

When a user navigates to an article, they’ll see the details of that article. We’ll need the API to support a way to retrieve an Article object by its id. Let’s say an article can also have rich UI elements like headers and code snippets. We would need to support a rich-text formatting language like Markdown. We can make the API return an article’s content in either Markdown or HTML through a field argument (`format`: HTML). Let’s also plan to display a "likes" counter in that view.

Put all these ideas on paper! The schema language is the most concise structured way to describe them:

``````type Query {
# ...
article(id: String!): Article!
}
enum ContentFormat {
HTML
MARKDOWN
}
type Article {
# ...
content(format: ContentFormat): String!
likes: Int!
}

``````

The one article’s UI view will also display the list of comments available on an article. Let’s keep the comment UI view simple and plan it to have a text content and an author name fields:

``````type Article {
# ...
commentList: [Comment!]!
}
type Comment {
id: ID!
content: String!
author: Author!
}

``````

Let’s focus on just these features. This is a good starting point that’s non-trivial. To offer these capabilities we’ll need to implement custom resolving logic for computed fields like `content(format: HTML)` and `readingMinutes`. We’ll also need to implement 1–1 and 1-many db relationships.

Did you notice how I came up with the whole schema description so far just by thinking in terms of the UI. How cool is that? You can give this simple schema language text to the front-end developers on your team and they can start building the front-end app right away! They don’t need to wait for your server implementation. They can even use some of the great tools out there to have a mock GraphQL server that resolves these types with random test data.

The schema is often compared to a contract. You always start with a contract.## Building a GraphQL Schema

When you’re ready to start implementing your GraphQL service, you have 2 main options (in JavaScript) today:

1. You can "build" a non-executable schema using the full schema language text that we have and then attach a set of resolver functions to make that schema executable. You can do that with GraphQL.js itself or with Apollo Server. Both support this method which is commonly known as "schema-first" or "SDL-first". I’ll refer to it here as the "full-schema-string method".
2. You can use JavaScript objects instantiated from the various constructor classes that are available in the GraphQL.js API (like `GraphQLSchema`, `GraphQLObjectType`, `GraphQLUnionType`, and many others). In this approach, you don’t use the schema-language text at all. You just create objects. This method is commonly known as "code-first" or "resolvers-first" but I don’t think these names fairly represent it. I’ll refer to it here as the "object-based method".

The schema language is a great programming-language-agnostic way to describe a GraphQL schema. It’s a human-readable format that’s easy to work with. The frontend people on your team will absolutely love it. It enables them to participate in the design of the API and, more importantly, start using a mocked version of it right away. The schema language text can serve as an early version of the API documentation.

However, completely relying on the full schema language text to create a GraphQL schema has a few drawbacks. You’ll have to put in some effort to make the code modularized and clear and you have to rely on coding patterns and tools to keep the schema-language text consistent with the tree of resolvers (AKA resolvers map). These are solvable problems.

The biggest problem I see with the full-schema-string method is that you lose some flexibility in your code. You don’t have objects associated with types. You just have strings! And although these strings make your types more readable, in many cases you’ll need the flexibility over the readability.

The object-based method is flexible and easier to extend and manage. It does not suffer from any of the mentioned problems. You have to be modular with it because your schema is a bunch of objects. You also don’t need to merge modules together because these objects are designed and expected to work as a tree.

The only problem I see with the object-based method is that you have to deal with a lot more code around what’s important to manage in your modules (types and resolvers). A lot of developers see that as "noise" and you can’t blame them. We’ll work through an example to see that.

If you’re creating a small-scope and well-defined GraphQL service, using the full-schema-string method is probably okay. However, in bigger and more agile projects I think the more flexible and more powerful object-based method is the way to go.

You should still leverage the schema-language text even if you’re using the object-based method. At jsComplete, we use the object-based method but every time the schema is built we use the `graphql.printSchema` function to write the complete schema to a file. We commit and track that file in the Git repository of the project and that proved to be a very helpful practice!
To compare the 2 methods, I’ve implemented an executable schema for the blog example we started with using both of them. I’ve omitted some code for brevity but kept what matters for the comparison.

### The full-schema-string method

We start with the schema-language text which defines 3 main custom types (`Article`, `Comment`, and `Author`). The fields under the main `Query` type are `article` and `articleList` which will directly resolve objects from the database. However, since the GraphQL schema we planned has custom features around an article object and since we have relations that we need to resolve as well we’ll need to have custom resolvers for the 3 main custom GraphQL types.

Here are a few screenshots for the code I wrote to represent the full-schema-string method. I’ve used Apollo Server here but this is also possible with vanilla GraphQL.js (and a bit more code).

Please note that this is just ONE way of implementing the full-schema-string method for this service. There are countless other ways. I am just presenting the simplest modular way here to help us understand the true advantages and disadvantages.

This is nice! We can see the types in the schema in one place. It’s clear where the schema starts. We’re able to modularize the code by type/feature.

This again is really great! Resolvers are co-located with the types they implement. There is no noise. This file beautifully contains what matters in a very readable format. I love it!

The modularity here is only possible with Apollo Server. If we’re to do this with vanilla GraphQL.js we will have to monkey with data objects to make them suitable to be a "resolvers tree". The mixing between the data structures and the resolvers graph is not ideal.
So what’s the downside here?

If you use this method then all your types have to be written in that certain way that relies on the schema language text. You have less flexibility. You can’t use constructors to create some types when you need to. You’re locked down to this string-based approach.

If you’re okay with that then ignore the rest of this article. Just use this method. It is so much cleaner than the alternative.

### The object-based method

Let’s now look at the object-based approach. Here’s the starting point of an executable schema built using that method:

We don’t need a separate `resolvers` object. Resolvers are part of the schema object itself. That makes them easier to maintain. This code is also easier to programmatically extend and analyze!

It’s also so much more code that’s harder to read and reason about! Wait until you see the rest of the code. I couldn’t take the `Article` type screenshot on the laptop screen. I had to use a bigger screen.

No wonder the full-schema-string method is popular! There is certainly a lot of "noise" to deal with here. Types are not clear at first glance. Custom resolvers are mixed in one big configuration object.

My favorite part is when you need to create a non-null list of non-null items like `[Article!]!`. Did you see what I had to write?

`new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(Article))),`

However, while this is indeed a lot more code that’s harder to understand, it is still a better option than having one big string (or multiple strings combined into one) and one big root resolvers object (or multiple resolvers objects combined into one). It’s better than having all the dependencies of your app managed in one single entry point.

There is a lot of power in modularizing your code using objects (that may depend on each other). It’s cleaner that way and it also makes writing tests and validations easier. You get more helpful error messages when you debug problems. Modern editors can provide more helpful hints in general. Most importantly, you have a lot more flexibility to do anything with these objects. The GraphQL.js constructors API itself also uses JavaScript objects. There is so much you can do with them.

But the noise is real too.

### The object-based method without the noise

I am sticking with the object-based method but I sure wish the JavaScript GraphQL implementations had a better API that can give us some of the power of the full-schema-string method.

Wouldn’t be nice if we can write the `Article` type logic exactly as we did in the full-schema-string method but in a way that generates the flexible `GraphQLObjectType` that we can plug into an object-based schema?

Something like:

Wouldn’t that be ideal? We get the benefits of the full-schema-string method for this type but with no lockdown! Other types in the system can be maintained differently. Maybe other types will be dynamically constructed using a different maker logic!

All we need to make this happen is a magical `<strong>typeMakerMethod</strong>` to take the parts that matter and transform them into the complete `GraphQLObjectType` for `Article`.

The `typeMakerMethod` will need to parse a string into an AST, use that to build a `GraphQLObjectType`, then merge the set of custom resolver functions with the `fields`configuration that’ll be parsed from the `typeDef` string.

I like a challenge so I dug a little bit deeper to see how hard would it be to implement the `typeMakerMethod`. I knew I couldn’t use the `graphql.buildSchema` function because it only parses one full schema string to make a non executable schema object. I needed a lower-level part that parses a string that has exactly ONE type and then attaches custom resolvers to it. So I started reading the source code of GraphQL.js to look for clues. A few cups of coffee later, I found some answers (in 2 places):

That’s the core method used in `buildSchema` to construct ONE type from a type definition node (which we can easily get by parsing the `typeDef` string).

And:

That’s how easy it is to extend an object type and attach any logic needed in `fields` and `interfaces`!

All I needed to do is put a few pieces together and the dream can be true.

Ladies and gentlemen. I present to you the magical "typeMakerMethod" (which I named `objectType`):

That’s it (in its most basic form)! This will take a `typeDef` string that defines a single GraphQL type, an object of resolvers and a map of dependencies (for that type), and it’ll return a `GraphQLObjectType` ready to be plugged into your object-based schema as if it was defined normally with the object constructor.

Now you can use the object-based method but you have the option to define SOME types using an approach similar to the full-schema-string method. You have the power.

What do you think of this approach? I’d love to hear your feedback!

Please note that the `objectType` code above is just the basic use case. There are many other use cases that require further code. For example, if the types have circular dependencies (`article``author``article`) then this version of `objectType` will not work. We can delay the loading of the circular dependencies until we’re in the `fields` thunk (which is the current approach to solve this problem in the object-based method). We can also use the "extend" syntax to design the schema in a way that avoids circular dependencies in the first place. I’ve skipped this part to keep the example simple.> If you’d like to give it a spin I published a more polished version of `objectType`and a few other maker functions like it under the graphql-makers npm package.

## JavaScript Tutorial: if-else Statement in JavaScript This JavaScript tutorial is a step by step guide on JavaScript If Else Statements. Learn how to use If Else in javascript and also JavaScript If Else Statements. if-else Statement in JavaScript. JavaScript's conditional statements: if; if-else; nested-if; if-else-if. These statements allow you to control the flow of your program's execution based upon conditions known only during run time.

Decision Making in programming is similar to decision making in real life. In programming also we face some situations where we want a certain block of code to be executed when some condition is fulfilled.
A programming language uses control statements to control the flow of execution of the program based on certain conditions. These are used to cause the flow of execution to advance and branch based on changes to the state of a program.

JavaScript’s conditional statements:

• if
• if-else
• nested-if
• if-else-if

These statements allow you to control the flow of your program’s execution based upon conditions known only during run time.

• if: if statement is the most simple decision making statement. It is used to decide whether a certain statement or block of statements will be executed or not i.e if a certain condition is true then a block of statement is executed otherwise not.
Syntax:
``````if(condition)
{
// Statements to execute if
// condition is true
}
``````

Here, condition after evaluation will be either true or false. if statement accepts boolean values – if the value is true then it will execute the block of statements under it.
If we do not provide the curly braces ‘{‘ and ‘}’ after if( condition ) then by default if statement will consider the immediate one statement to be inside its block. For example,

``````if(condition)
statement1;
statement2;

// Here if the condition is true, if block
// will consider only statement1 to be inside
// its block.
``````

Flow chart:

Example:

``````<script type = "text/javaScript">

// JavaScript program to illustrate If statement

var i = 10;

if (i > 15)
document.write("10 is less than 15");

// This statement will be executed
// as if considers one statement by default
document.write("I am Not in if");

< /script>

``````

Output:

``````I am Not in if
``````
• if-else: The if statement alone tells us that if a condition is true it will execute a block of statements and if the condition is false it won’t. But what if we want to do something else if the condition is false. Here comes the else statement. We can use the else statement with if statement to execute a block of code when the condition is false.
Syntax:
``````if (condition)
{
// Executes this block if
// condition is true
}
else
{
// Executes this block if
// condition is false
}
``````

Example:

``````<script type = "text/javaScript">

// JavaScript program to illustrate If-else statement

var i = 10;

if (i < 15)
document.write("10 is less than 15");
else
document.write("I am Not in if");

< /script>

``````

Output:

``````i is smaller than 15
``````
• nested-if A nested if is an if statement that is the target of another if or else. Nested if statements means an if statement inside an if statement. Yes, JavaScript allows us to nest if statements within if statements. i.e, we can place an if statement inside another if statement.
Syntax:
``````if (condition1)
{
// Executes when condition1 is true
if (condition2)
{
// Executes when condition2 is true
}
}
``````

Example:

``````<script type = "text/javaScript">

// JavaScript program to illustrate nested-if statement

var i = 10;

if (i == 10) {

// First if statement
if (i < 15)
document.write("i is smaller than 15");

// Nested - if statement
// Will only be executed if statement above
// it is true
if (i < 12)
document.write("i is smaller than 12 too");
else
document.write("i is greater than 15");
}
< /script>

``````

Output:

``````i is smaller than 15
i is smaller than 12 too
``````
• if-else-if ladder Here, a user can decide among multiple options.The if statements are executed from the top down. As soon as one of the conditions controlling the if is true, the statement associated with that if is executed, and the rest of the ladder is bypassed. If none of the conditions is true, then the final else statement will be executed.
``````if (condition)
statement;
else if (condition)
statement;
.
.
else
statement;
``````

Example:

``````<script type = "text/javaScript">
// JavaScript program to illustrate nested-if statement

var i = 20;

if (i == 10)
document.wrte("i is 10");
else if (i == 15)
document.wrte("i is 15");
else if (i == 20)
document.wrte("i is 20");
else
document.wrte("i is not present");
< /script>

``````

Output:

``````i is 20
``````