JavaScript Notes
JavaScript Notes
To create a variable, we will write let and then the variable name , then equals to then a string in single quotes.
What this will do is, it create a binding between variable name and its value. Now, from now on this variable name
can be used if you want to use the value it is pointing to.
[Link](anotherName); // Lionel
As we know firstName is pointing to ‘Lionel’ in memory. anotherName will also point to ‘Lionel’ now.
So the output will be ‘Lionel’
[Link](anotherName); // 'LionelMessi';
If we add two strings, it will create a new string with one string concatenated to another.
Now, anotherName is pointing to ‘LionelMessi’
All three are strings, the only difference is the first and last string are referenced through variable and the middle is
string is written as it is.
This is the use case of variables, we dont have to write ‘Lionel Messi’ everywhere. We can just use anotherName
variable.
You can not use multiplication, division and subtraction with strings, only addition which will cause
concatenation.
'Hello world'
"Hello world"
`Hello world`
Backslash has some special powers inside strings. Whenever a \ is found inside string, it indicates the character
after it has some special meaning. This is called escaping characters.
For example, if you want to create a line break, between characters, you can use \n
[Link](firstName);
/*
Lionel
Messi
*/
If you want to use single quote inside a string with single quotes.
let greeting = 'My name is ' + firstName + ' ' + lastName + '. I live in ' + state + '. My favorite lang is ' + favLang;
let greeting2 = `My name is ${firstName} ${lastName}. I live in ${state}. My favorite lang is ${favLang}`;
[Link](greeting);
[Link](greeting2);
As you have seen, we have used let keyword for both strings and numbers.
In javascript there is no different data types for float and negative numbers.
let num = 20 + 3 * 4;
[Link](num); // 32
Precedence of operators
Parenthesis have highest precedence
Numbers 1
If two operators have same precedence, then value is calculated from left to right.
Numbers 2
Some things about variables
You can not redefine variables declared with let
There is one interesting thing about Javascript, is that it is weakly typed, which
means we can reassign one variable to different types.
something = 20;
[Link](something); // 20
C++ is a strongly typed language. You can assign a variable of one type to another.
[Link](hello); // true
[Link](other); // false
[Link](to);
Booleans 1
Decision making
IF
Syntax for if statement is given below.
For example
You dont usually write these true and false directly, you write some condition inside
it.
Similary
This is because if statement will run only the single statement. If you want to run
multiple statement for the if statement, you have to create a block.
Decision making 1
{
[Link]('Line one');
[Link]('Line two');
}
With the help of if statement, we are able to conditionally execute some lines.
ELSE
If you want to run something, if the condition fails, we can use else
IF ELSE
We can also apply multiple conditions using if-else
Decision making 2
It will run the statement belonging to the first condition which is true.
Decision making 3
Logical Operators
&&
Both condition needs to be true.
||
Logical OR operator means, any one can be true
!
Logical not operator. Its a unary operator. It flips the value given to it.
if (!isPassed) {
[Link]('Fail');
}
As soon as the final result of the logical operation is known, execution stops.
Logical Operators 1
[Link]('Pass!!');
}
In the above code firstName is not defined, still code workds fine.
This is because, execution stops as soon as it check score > 33 is true.
Logical Operators 2
Functions
Functions
Functions are the programs within a program. We can run it multiple times within a
program.
function function_name() {
// code to run
}
function sum() {
let num1 = 10;
let num2 = 30;
[Link](num1 + num2);
}
function sum() {
let num1 = 10;
let num2 = 30;
[Link](num1 + num2);
}
sum(); // 40
function sum() {
let num1 = 10;
let num2 = 30;
[Link](num1 + num2);
}
Functions 1
sum();
sum();
sum();
sum();
function sum(num3) {
let num1 = 10;
let num2 = 30;
sum(10); // 50
function sum(num3) {
let num1 = 10;
let num2 = 30;
sum(10); // 50
sum(30); // 80
sum(90); // 130
The first time the function runs, num3 will be pointing to 10, the second time, num3
function sum(num2) {
let num1 = 20;
let ans = num1 + num2;
return ans;
}
Functions 2
sum(20);
You can use return statement only once inside a function. You are calculating the
answer and returning its value.
function sum(num2) {
let num1 = 20;
let ans = num1 + num2;
return ans;
}
Functions 3
undefined and null
How do we declare a variable?
[Link](someVariable); // Lionel
let someVariable;
[Link](someVariable); // ??
let email;
let email;
email = 'abc@[Link]'
function greeting(firstName) {
[Link](firstName); // Lionel
}
greeting('Lionel');
function greeting(firstName) {
[Link](firstName); // undefined
}
greeting();
function sum(num1) {
[Link](num1);
}
result variable is going to store the value, whatever returned from the function. But
what if nothing is returned from the function. Then in that case, result variable will
be pointing to undefined .
From above examples, we can see that undefined gets implicitly assigned by the JS,
if we ourselves do not assign some value.
Sometimes, in your program you want to clear some value. For example when user
clear the form or clear the input field, unselect the dropdown, etc.
[Link](email); // undefined
But there is one problem with the above approach. We do not know, the variable is
not defined or the variable is explicitly set undefined. And sometimes it is very
important to know the difference.
So, for this JS gave us another data type called null which also represents no
value .
[Link](email); // null
sum();
sum();
Now, if num2 is not provided, its value is going to be 20. If you provide num2 , it will
take that value
num1 will take the value provided and num2 will take the default value.
let todo = {
title: 'Buy groceries',
completed: false,
due: 10
}
[Link](todo)
Just like we define other variables with let keyword, we do the same with object.
Object starts with curly braces and inside that we have to write key-value pairs. Keys
are called properties and values can be anything, number, string, Boolean, function
or object.
Dot notation
We can access properties from todo using the dot notation.
For example, if we want to print the title of the todo
let todo = {
title: 'Buy groceries',
completed: false,
due: 10
}
Objects 1
[Link]([Link]); // Buy groceries
[Link](`The title of the book is ${[Link]}`);
Changing properties
We can also change the property of an object.
let todo = {
title: 'Buy groceries',
completed: false,
due: 10
}
[Link]([Link]); // false
[Link] = true;
[Link]([Link]); // true
Challenge
Create a note object with title, description and pages properties.
Objects 2
Methods
Methods are nothing but object properties that are function.
As we have seen, object properties can be number, string and Boolean, but object
properties can also be functions.
Syntax:
let marks = {
pa: 90,
fnd: 100,
nalr: 0,
totalMarks: function() {
return 90 + 100 + 0;
}
}
[Link]([Link]()); // 190
let marks = {
pa: 90,
fnd: 100,
nalr: 0,
totalMarks: function(fine) {
return 90 + 100 + 0 - fine;
}
}
[Link]([Link](50)); // 140
But it will be better if we don’t have to hardcode marks and use the marks on the
object itself.
JS provide a special keyword called this . The value of this is the object itself on
which the method is called.
You can print the value of this on the console.
let marks = {
pa: 90,
fnd: 100,
nalr: 0,
totalMarks: function(fine) {
Methods 1
[Link](this);
return 90 + 100 + 0 - fine;
}
}
[Link]([Link](50)); // 140
Now, you can access properties of the object using dot notation on this .
let marks = {
pa: 90,
fnd: 100,
nalr: 0,
totalMarks: function(fine) {
[Link](this);
return [Link] + [Link] + [Link] - fine;
}
}
[Link]([Link](50)); // 140
Methods 2
Arrays
Arrays are used to store collection of multiple items under a single variable name.
[Link](arr[0]); // Messi
[Link](arr[2]); // Neymar
If we try to acces the index that does not exist, we will not get an error, we will get
undefined .
[Link](arr[10]); // undefined
Setting items
You can also set item at a particular index
Arrays 1
Array properties and methods
length
To get the number of items in an array, there is a property on array which you can
access
push()
Now, lets say, you have to add items to the array, you can use push() method on an
array. You have to pass the item you want to add to the push() method.
[Link]('ST-2');
[Link](todo); // ['Buy groceries', 'Complete assignment', 'ST-1', 'ST-2'];
pop()
We can also remove item from the end of an array using pop() . pop() method also
returns the remove item which you can store in a variable.
unshift()
shift()
join()
This method returns the string. by concatenating all the elements of any array.
By default it will use comma as a separator. You can pass different separators
includes()
Return true or false depending upon whether an array includes a certain element or
not.
[Link]([Link]('ST-2')); // false
for loop
for…of loop
There is one more syntax which you can use to loop through array.
for…in loop
let obj = {
english: 80,
maths: 90,
Loops 1
hindi: 70
}
break
If you want to break out of the loop at a certain point, we can use break keyword
[Link](arr[i]);
}
continue
If you want to continue the loop, without executing the remaining code, we can use
continue keyword.
[Link](arr[i]);
}
Loops 2
3 ways to declare a variable
We have seen one keyword let using which we are declaring variables.
There are two more keywords using which we can declare variables.
const
Just like let , we can declare variables using const keyword.
[Link](email);
Difference between let and const is that, with const you can not reassign
variables.
const person = {
username: 'messi',
};
person = {
username: 'messi'
}; // Error
Here, personvariable is still pointing to the same object. You are not reassigning
person variable.
Another difference between let and const is that with const you cannot just
declare variables and not assign it.
In case of let , it is okay to declare a variable but not assign it. JS will automatically
assign undefined to it. In case of const , it is compulsary to assign it a value.
var
var is similar to let . Previously there is only one way to declare variables and that
is using var , but JS introduced two more keywords let and const to declare
variables.
username = 'world';
[Link](username); // world
The difference between var and let is that with var you can redeclare variables.
[Link](username); // world
Before executing any line of code, JS Engine will create an execution context. The
first EC that is created is called Global Execution Context.
What JS engine will do is skim out all the variables and functions which are in global
scope.
var person = {
email: 'abc@[Link]',
password: 'something-secure'
};
[Link](username);
For example
First, memory creation phase will run. In memory creation phase, all variables get
skimmed out and are assinged undefined .
Its not the variables that are skimmed out during memory creation phase. Functions
are also skimmed out. But in case of functions, undefined is not assigned, but the
whole function gets stored there.
function sum() {
var num1 = 10;
var num2 = 20;
sum();
[Link](username);
As we have discussed, during memory creation phase, variables and functions are
skimmed out.
And when all of the code gets executed, Global execution context also gets
destroyed.
Call stack
These execution contexts are managed inside a stack called Call Stack.
Execution contexts are pushed and poped from this call stack.
var a = 20;
function myFunc() {
[Link]('Inside my function');
}
[Link](a); // 20
myFunc(); // Inside my function
[Link](a); // undefined
myFunc(); // Inside my function
var a = 20;
function myFunc() {
[Link]('Inside my function');
}
Question
function a() {
[Link](b); // undefined
var b = 20;
}
a();
Hoisting 1
Scopes
What will be the output of below code?
var b = 20;
function a() {
[Link](b); // 20
}
a();
There is a concept called scopes. This concept is present in almost all programming
languages.
Scope for a variable roughly can be defined, where that variable can be accessed.
For example, in the above case, variable b has global scope. It can be accessed
any where in the code.
When the function execution context is created, it will try to find b in its local scope
(or memory). If it does not find it there, it will try to find it in the lexical scope (or
memory or environment) of its parent.
Scopes 1
Another example
function outer() {
var b = 10;
inner();
function inner() {
[Link](b); // 10
}
}
outer();
Then the outer() function will be called. To run that function, an execution context is
created and its memory creation phase is run.
Scopes 2
Then inner function will be called. The execution context for inner function will be
created.
When the inner function is executed line by line, it will look for variable b in its local
scope. When it does not find it there, it will look it in the lexical environment of its
parent. This chain of lexical environment is called Scope Chaining
function outer() {
inner();
var b = 10;
Scopes 3
function inner() {
[Link](b); // undefined
}
}
outer();
Scopes 4
More differences between var,
let and const
Blocks
To understand this concept, we must know what is a block in javascript. You can
create a block using curly braces.
The above code is a valid JS code. We have used blocks in if statement when we
have to use multiple statements inside if .
{
[Link]('Hello world');
}
[Link]('Hello India');
Scope
let and const are block scoped while var is a function scoped. That means the
variables declared using let is only accessible inside the block it is declared.
Variable x is only accessible inside the if statement. As soon as the block ends,
the variable x gets vanished. Outside the if block, there is no variable x , so you
will get an error.
Question
What will be the output of below code?
let x = 10;
{
let x = 20;
[Link](x); // 20
}
[Link](x); // 10
As let is block scoped, it will not conflict with that in global scope.
Question
What will be the output of below code?
var x = 10;
{
var x = 20;
[Link](x); // 20
}
[Link](x); // 20
Hoisting
Question
[Link](a); // undefined
[Link](b); // Cannot access b before initialization
[Link](c); // Cannot access c before initialization
var a = 10;
let b = 20;
const c = 30;
let and const are hoisted but they remain in temporal dead zone. You can not
access those variables declared with let and const until they are in temporal dead
zone. They remain in temporal dead zone till they are initialized.
Take a look at the error. Error is not that it is not defined. The error is you can not
access them before initialization.
function a(fn) {
[Link]('Inside a');
fn();
}
function b() {
[Link]('Inside b');
}
a(b);
// Inside a
// Inside b
You don’t have to declare a new function to pass to another function. You can
declare inside an argument directly like below.
function a(fn) {
[Link]('Inside a');
fn();
}
// function b() {
// [Link]('Inside b');
// }
a(function() {
[Link]('Inside b');
});
// Inside a
// Inside b
function a() {
function b() {
[Link]('inside b')
}
function getString(arr) {
let result = [];
return result;
}
function getNumber(arr) {
let result = [];
return result;
}
function getBoolean(arr) {
let result = [];
return result;
}
let arr = [120, 'Hello', 90, false, 'World', true, 20, 80, 'Messi'];
As you can see, you are repeating a lot of code. You can extract out the logic of
checking item and pushing it into the array as it is same for all the 3 functions. The
changing part is the condition. We can pass a function to check for 3 conditions.
function getString(item) {
return typeof item === 'string';
}
function getNumber(item) {
return typeof item === 'number';
}
function getBool(item) {
return typeof item === 'boolean';
}
return result;
}
let arr = [120, 'Hello', 90, false, 'World', true, 20, 80, 'Messi'];
[Link](get(arr, getString));
[Link](get(arr, getNumber));
[Link](get(arr, getBool));
We are passing function whose job is check for different type into a function whose
job is to check and push items into the array. Separation of concern.
You can create variable for a function and then pass or you can directly declare a
function inside an argument.
[Link](function(item) {
[Link](item);
})
/*
Messi
Ronaldo
Neymar
Zlatan
*/
[Link](function(item, index) {
[Link](`${item} at index ${index}`);
})
/*
Messi at index 0
Ronaldo at index 1
Neymar at index 2
Zlatan at index 3
*/
map()
This method also takes callback function as an argument, but return a new array
populated by the result of calling that callback function. The function you pass in as a
filter()
This method also takes callback as a function and return a new array. The callback
function will be called for each item.
If you return true, then that item will be included in the new array otherwise it will not
be included.
[Link](evenMarks); // [2, 4, 6, 8]
[Link](marks); // [1, 2, 3, 4, 5, 6, 7, 8]
There are many other methods, you can read them on MDN docs.
function someFunc() {
let username = 'Lionel';
function printName() {
[Link](username);
}
printName();
}
someFunc(); // Lionel
What will be the output of below function? As already discussed, inner function will
have access to the lexical environment of its parent.
So function printName will have access to username variable which out of its scope
but is in the lexical scope of its parent.
Now, what if, instead of calling printName function inside someFunc , we return
printName function and call it outside the scope of someFunc , like below. What will be
the output?
function someFunc() {
let username = 'Lionel';
function printName() {
[Link](username);
}
return printName;
}
let fn = someFunc();
fn(); // Lionel
It will print Lionel , even though the username variable is not in its scope.
How, is it working? How printName function has access to username variable even
though it is not in its scope?
This is a closure → A function bundled together with references to its surrounding
state or we can say lexical environment is called closure.
Closures 1
When printName function was defined, it has access to username variable. So, it will
always have access to username variable even though the variable is not in its scope
or its parent scope.
Use of closure
There are many uses of closures, one of them is
Lets say you want to build a counter. But you dont want user to update count directly
but give them some methods like increment , decrement to change the value of count.
You can do is easily in other languages with classes and private property count . In
JS, you can use closure.
function counter() {
let count = 0;
return {
getCount: function() {
return count;
}
};
}
We are creating a function counter which is going to return an object though which
we can change the value of count variable using closures. As you can see, end user
will only have access to the object with getCount method. User have no access to
count variable. So they can’t manipulate it directly.
You can provide different methods to manipulate count for end user.
function counter() {
let count = 0;
return {
getCount: function() {
return count;
},
Closures 2
increment: function() {
count += 1;
},
decrement: function() {
count -= 1;
},
reset: function() {
count = 0;
}
};
}
Closures 3
Prototypes
Consider the below example
let todo = {
title: 'Buy groceries',
desc: function() {
return `You have to ${[Link]}`;
}
};
We also accessed toString method on todo object. But this method does not exist
on todo object. We should be getting undefined , but instead we are getting some
value, which indicates that this method do exist on the todo object. How is it
possible?
There is a thing in Javascript called Prototypes .
If you try to access a property of an object, what JS will do is, it will try to find that
property in the object. If it fails to find that property, then it will search its prototype for
the property. Prototype is another object which is used as a fallback source of
properties.
Prototypes 1
When you try to access toString property on an object, it will first search the object
for that property. It didn’t find that property. Then it will search the prototype of that
property which is [Link] . It will find that property and displays the result.
So, prototype is just another object which is used as a fallback source for properties.
Every object in Javascript has a prototype.
You can check the prototype of any object using __proto__ property.
So,
As, we have seen [Link] is an object, so it must have its own prototype.
What is the prototype of [Link] . It is null .
This chain of prototypes is called Prototypal chain . As there must be an end to this
chain, the prototype of [Link] is null .
Prototypes 2
Every object by default has a prototype which is [Link] .
If you create another object, that too has [Link] as its prototype.
So, arrays are basically an object, on which we can access properties and methods.
Prototypes 3
For example, we can access length property.
We have seen the object to which an array is converted to. But that object do not
have push and pop properties. Where do those properties come from.
These properties come from its prototype. As we have discussed that when we try to
access the property on an array, it is converted to an object. So that object has a
prototype which has all these properties and methods, push , pop , shift , unshift ,
etc.
methods on strings?
Just like arrays, strings are converted to objects when you try to access properties
on that string.
Prototypes 4
Inheritance
Prototypes can be considered as inheritance, as it can be looked as objects are
inheriting the properties of [Link] .
Prototypes 5
Constructor functions
What will be the output of below code?
function user() {
[Link](user1); // undefined
We have already discussed that, if you don’t return anything from the function then
undefined is returned.
function user() {
[Link](user1); // {}
We can add properties to the object that is being generated using the this keyword.
function user() {
[Link] = 'Zeeshan';
[Link] = 'abc@[Link]';
}
const user1 = new user();
[Link](user1); // { username: 'Zeeshan', email: 'abc@[Link]' }
Constructor functions 1
function user(username, email) {
[Link] = username;
[Link] = email;
}
let user1 = new user('messi', 'messi@[Link]');
[Link](user1);
let user2 = new user('ronaldo', 'ronaldo@[Link]');
[Link](user2);
[Link] = function() {
return `My name is ${[Link]}`;
}
}
let user1 = new user('messi', 'messi@[Link]');
[Link]([Link]()); // My name is messi
let user2 = new user('ronaldo', 'ronaldo@[Link]');
[Link]([Link]()); // My name is ronaldo
You can add as many properties you want and all the generated objects will have the
same properties.
[Link] = function() {
return `My name is ${username}`;
}
}
let user1 = new User('messi', 'messi@[Link]');
[Link]([Link]()); // My name is messi
Constructor functions 2
As we have seen, if we generate objects using curly brace notation, its prototype will
be [Link] . What will be the prototype of the objects generated from
constructor functions. Its prototype will be an object with one property called
constructor whose value is the constructor function itself.
You have created your own custom data type. Just like there are Array datatype,
String datatype., now there is User datatype. You can create new objects of that
datatype using new keyword.
Now, as you have seen the description method is same for all objects. It will be
better that we move that description method to [Link].
Constructor functions 3
function User(username, email) {
[Link] = username;
[Link] = email;
}
[Link] = function() {
return `My name is ${[Link]}`;
}
Constructor functions 4
Now, when we try to access description property on user1 object, it didn’t exist. So it
will check its prototype for that method.
Constructor functions 5
Class syntax
Just like let and const , classes are very new to Javascript. It is just an alternative
way to write constructor functions. It is just the Syntactic sugar. It is doing the exact
same thing as constructor function, its just the sytax is different.
Consider the below constructor function. We have to convert this into Class syntax.
[Link] = function() {
[Link](`My username is ${[Link]}`);
}
[Link] = function() {
return `${[Link]} ${[Link]}`;
}
The syntax for class, is we have to start witl class keyword and then name of that
class.
You can literally copy paste the constructor function.
class Person {
constructor(firstName, lastName, email) {
[Link] = firstName;
[Link] = lastName;
[Link] = email;
}
}
You can add methods too. In this case too, you just have to copy paste. Its just the
syntax is different, functionality is same.
class Person {
constructor(firstName, lastName, email) {
Class syntax 1
[Link] = firstName;
[Link] = lastName;
[Link] = email;
}
getFullName() {
return `${[Link]} ${[Link]}`;
}
}
We are getting the exact same behavior as we got with constructor function.
Inheritance
Lets say we want to create a Student class which has all the properties and methods
of Person class. One way is to define a new class and add all properties and
methods again on that class.
Lets say we want to create a class called Student with all the properties of Person
class. One way is to copy all the properties and methods from Peron class.
class Person {
constructor(firstName, lastName, email) {
[Link] = firstName;
[Link] = lastName;
[Link] = email;
}
getFullName() {
return `${[Link]} ${[Link]}`;
}
}
Class syntax 2
We can inherit all properties and methods of one class using extends keyword.
Now Student class has all the properties ( firstName , lastName and email ) and all the
methods ( constructor and getFullName ) of parent class Person .
For example, if you want to add some additional fields including already existed
fields to Student class like groupNo . You can override the constructor function
because that’s where you are initializing properties
class Person {
constructor(firstName, lastName, email) {
[Link] = firstName;
[Link] = lastName;
[Link] = email;
}
getFullName() {
return `${[Link]} ${[Link]}`;
}
}
Now, the objects created using Student class will have groupNo property.
class Person {
constructor(firstName, lastName, email) {
[Link] = firstName;
[Link] = lastName;
Class syntax 3
[Link] = email;
}
getFullName() {
return `${[Link]} ${[Link]}`;
}
}
getFullName() {
return `My name is ${[Link]} ${[Link]}`;
}
}
Just like you have defined new properties on Student class, you can also define new
methods on it.
Class syntax 4
Async programming
Javascript is a synchronous single threaded language.
Single threaded means that Javascript engine can execute only one statement at a
time. It can not run multiple statements. It has a single call stack to execute the
statement. It does not have multiple call stacks to run statements in parallel.
[Link]('start');
[Link]('end');
There is something called setTimeout which is being provided by the browser which
will help you to run some code after some time.
[Link]('start');
setTimeout(function() {
[Link]('run after 4 seconds');
}, 4000);
[Link]('end');
In setTimeout , you have to pass a callback function as first argument and then time in
milliseconds as a second argument. The callback function will run after 4 seconds.
What will happen, first start will print, then end will print instantly then after 4
seconds run after 4 seconds will print.
But how is it possible? We just discussed that JS will wait for none. And it will
execute statements in single order. So, how JS is running [Link] after 4
seconds.
Async programming 1
is not a part of JS. Javascript Engine do not have a timer to time for
setTimeout
4seconds and then run the code. It is the browser that has timer and provide us this
setTimeout function.
Browser has many other useful things like console, local storage, session storage,
fetch, viewport, location and many other things.
Browser provide these things to the javascript engine. Javscript as a language has
no local storage, timer, location and other things.
Browser provide these things using Web APIs. Basically, browser provide some
objects, some functions to JS Engine which we can use to access these
functionalities.
through Javascript.
Lets see how does these things work behind the scenes.
Async programming 2
[Link]('start');
setTimeout(function() {
[Link]('run after 4 seconds');
}, 4000);
[Link]('end');
When first line is executed, JS engine will access the console from the browser and
print start on the console.
Then the second line will be executed, what it wil do is, it will contact the browser.
Browser will start a timer for 4 seconds and register a callback function.
Async programming 3
After a callback is registered, javascript engine will move to the next line for
execution. It will not wait for 4 seconds to run the callback function because JS is
synchronous.
It will execute the last line and print end in the console.
Async programming 4
As the last line is executed, global execution context is popped out of the call stack.
How will that callback which is registered to run after 4 seconds be executed?
As we know, in Javascript everything is executed inside the execution context which
is inside the call stack. So, it is the duty of browser now to send that callback
function to the call stack.
Lets see how, browser send that callback function to the call stack.
Async programming 5
When 4 seconds elapsed, the registered callback is pushed to the callback
queue and will wait for its turn.
What even loop will do is, it will keep and eye on call stack. As soon as the call
stack gets empty, event loop will push the callback from callback queue in the
call stack to get executed.
As callback is a function, it will create its own execution context and start executing
the code inside it. It will print run after 4 seconds to the console.
Async programming 6
So, the job of callback queue is to hold all the callbacks that are registered for their
turn.
The job of event loop, is to keep an eye on the call stack. Once call stack get empty,
event loop will start pushing callback functions to the call stack.
Question
[Link]('start');
setTimeout(function() {
[Link]('run after 2 seconds');
}, 2000);
setTimeout(function() {
[Link]('run after 4 seconds');
}, 4000);
[Link]('end');
/*
start
end
run after 2 seconds
run after 4 seconds
*/
Question
[Link]('start');
setTimeout(function() {
[Link]('run after 0 seconds');
}, 0);
[Link]('end');
/*
start
end
run after 0 seconds
*/
Async programming 7
Callback Hell
Lets say you are buiding an application like instagram or instagram clone. And you
want to allow users to upload their pictures. Now, what functions will you write to
allow user to upload their pictures.
When user click on upload button, you will run a function called step1 that will open
a file explorer or camera to chose image.
Once user selects image, you will run another function step2 and pass that selected
image to that function. This function step2 will let user to add filters to their image.
Then you will allow user to add caption. For that you will write another function, lets
say step3 for that which will take that filtered photo as argument and let user add
caption to the image.
Then, it the last step, you will write a function step4 to finally upload the image. That
function will take final image and caption as argument.
We are going to mock this behaviour. Lets say each function take some time to
complete and one function is dependant on another.
Callback Hell 1
How are you going to achieve this? One function should run after completion of the
previous function and also have the output of the previous function.
function step1() {
setTimeout(function() {
[Link]('Selecting image');
return 'image';
}, 4000);
Callback Hell 2
}
function step3(filteredImage) {
setTimeout(function() {
[Link](`Adding caption to ${filteredImage}`);
return 'filtered image with caption';
}, 3000);
}
function step4(final) {
setTimeout(function() {
[Link](`${final} uploaded`);
}, 2000);
}
You can try calling these function like below. Will it work?
/*
Applying filters to undefined
undefined uploaded
Adding caption to undefined
Selecting image
*/
But this will not work as Javascript will not wait for step1 function to complete and it
instantly calls step2 function, then step3 and then step4 instantly.
Also another problem is step2 takes least time to finish, so it gets printed first and
then step4 , then step3 and at last step1 . This is not what we want. We want it to run
sequentially, in order.
Callback Hell 3
What we will do is, we will pass callback functions to each step and will run that
callback function when that step ends.
function step1(fn) {
setTimeout(function() {
[Link]('Selecting image');
// return 'image';
fn('image');
}, 4000);
}
step1(function(image) {
step2(image);
});
Now, we want step3 to run after step2 gets completed. So same like above, we will
pass a callback function to step2 whose job will be to call step3 with required
arguments.
step2 will pass filteredImage to callback function and then that callback function will
pass that to step3 .
function step1(cb) {
setTimeout(function() {
[Link]('Selecting image');
// return 'image';
cb('image');
}, 4000);
}
Callback Hell 4
}, 2000);
}
function step3(filteredImage) {
setTimeout(function() {
[Link](`Adding caption to ${filteredImage}`);
return 'filtered image with caption';
}, 3000);
}
function step1(cb) {
setTimeout(function() {
[Link]('Selecting image');
// return 'image';
cb('image');
}, 4000);
}
function step4(final) {
setTimeout(function() {
[Link](`${final} uploaded`);
}, 2000);
}
step1(function(image) {
step2(image, function(filteredImage) {
step3(filteredImage, function (finalImage) {
step4(finalImage);
});
});
});
Now, everything will work as expected. step2 will be called after 4 seconds with
required argument. Then after 2 seconds step3 will be called and after 3 seconds
Callback Hell 5
step4 will be called with required arguments.
Pros
Pros are that you can call one function after the completion of other function in
sequential order. Basically you can do async stuff using callbacks
Cons
There are 2 problems with this approach.
One is quite evident is that our code is growing horizontly instead of vertically. As we
add more callbacks, it will get difficult to maintain the codebase.
Another problem with this code is that we are giving the power to call step2 to
step1 .
What if step2 never get called. In this case we ourselves are writing step1 . But it
might not be the case everytime.
Solution
You can solve these problems using Promises.
Callback Hell 6
Callback Hell 7