Title - Namaste JavaScript
Title - Namaste JavaScript
In the container the first component is memory component and the 2nd one is code
component
Memory component has all the variables and functions in key value pairs. It is also called
Variable environment.
Code component is the place where code is executed one line at a time. It is also called the
Thread of Execution.
JS is a synchronous, single-threaded language
[Link] 1/82
12/09/2025, 21:19 title: Namaste JavaScript
var n = 2;
function square(num) {
var ans = num * num;
return ans;
}
var square2 = square(n);
var square4 = square(4);
The very first thing which JS does is memory creation phase, so it goes to line one of above
code snippet, and allocates a memory space for variable 'n' and then goes to line two, and
allocates a memory space for function 'square'. When allocating memory for n it stores
'undefined', a special value for 'n'. For 'square', it stores the whole code of the function
inside its memory space. Then, as square2 and square4 are variables as well, it allocates
memory and stores 'undefined' for them, and this is the end of first phase i.e. memory
creation phase.
[Link] 2/82
12/09/2025, 21:19 title: Namaste JavaScript
Now, in 2nd phase i.e. code execution phase, it starts going through the whole code line by
line. As it encounters var n = 2, it assigns 2 to 'n'. Until now, the value of 'n' was undefined.
For function, there is nothing to execute. As these lines were already dealt with in memory
creation phase.
Coming to line 6 i.e. var square2 = square(n), here functions are a bit different than any
other language. A new execution context is created altogether. Again in this new
execution context, in memory creation phase, we allocate memory to num and ans the two
variables. And undefined is placed in them. Now, in code execution phase of this execution
context, first 2 is assigned to num. Then var ans = num * num will store 4 in ans. After that,
return ans returns the control of program back to where this function was invoked from.
When return keyword is encountered, It returns the control to the called line and also the
function execution context is deleted. Same thing will be repeated for square4 and then
[Link] 3/82
12/09/2025, 21:19 title: Namaste JavaScript
after that is finished, the global execution context will be destroyed. So the final diagram
before deletion would look something like:
Javascript manages code execution context creation and deletion with the the help of Call
Stack.
Call Stack is a mechanism to keep track of its place in script that calls multiple function.
Call Stack maintains the order of execution of execution contexts. It is also known as
Program Stack, Control Stack, Runtime stack, Machine Stack, Execution context stack.
[Link] 4/82
12/09/2025, 21:19 title: Namaste JavaScript
It should have been an outright error in many other languages, as it is not possible to even
access something which is not even created (defined) yet But in JS, We know that in
memory creation phase it assigns undefined and puts the content of function to function's
memory. And in execution, it then executes whatever is asked. Here, as execution goes line
by line and not after compiling, it could only print undefined and nothing else. This
phenomenon, is not an error. However, if we remove var x = 7; then it gives error. Uncaught
ReferenceError: x is not defined
Hoisting is a concept which enables us to extract values of variables and functions even
before initialising/assigning value without getting error and this is happening due to the 1st
phase (memory creation phase) of the Execution Context.
So in previous lecture, we learnt that execution context gets created in two phase, so even
before code execution, memory is created so in case of variable, it will be initialized as
undefined while in case of function the whole function code is placed in the memory.
Example:
Now let's observe a different example and try to understand the output.
[Link] 5/82
12/09/2025, 21:19 title: Namaste JavaScript
function a() {
var x = 10; // local scope because of separate execution context
[Link](x);
}
function b() {
var x = 100;
[Link](x);
}
Outputs:
10
100
[Link] 6/82
12/09/2025, 21:19 title: Namaste JavaScript
The Global Execution Context (GEC) is created (the big box with Memory and Code
subparts). Also GEC is pushed into Call Stack
In first phase of GEC (memory phase), variable x:undefined and a and b have their entire
function code as value initialized
In second phase of GEC (execution phase), when the function is called, a new local
Execution Context is created. After x = 1 assigned to GEC x, a() is called. So local EC for a
is made inside code part of GEC.
For local EC, a totally different x variable assigned undefined(x inside a()) in phase 1 , and in
phase 2 it is assigned 10 and printed in console log. After printing, no more commands to
run, so a() local EC is removed from both GEC and from Call stack
Call Stack :[GEC, b()] -> GEC (after printing yet another totally different x value as 100 in
console log)
Finally GEC is deleted and also removed from call stack. Program ends.
reference:
[Link] 7/82
12/09/2025, 21:19 title: Namaste JavaScript
eg:
var x = 10;
[Link](x); // 10
[Link](this.x); // 10
[Link](window.x); // 10
[Link] 8/82
12/09/2025, 21:19 title: Namaste JavaScript
When variable is declared but not assigned value, its current value is undefined. But
when the variable itself is not declared but called in code, then it is not defined.
[Link](x); // undefined
var x = 25;
[Link](x); // 25
[Link](a); // Uncaught ReferenceError: a is not defined
JS is a loosely typed / weakly typed language. It doesn't attach variables to any datatype.
We can say var a = 5, and then change the value to boolean a = true or string a = 'hello'
later on.
Never assign undefined to a variable manually. Let it happen on it's own accord.
[Link] 9/82
12/09/2025, 21:19 title: Namaste JavaScript
// CASE 1
function a() {
[Link](b); // 10
// Instead of printing undefined it prints 10, So somehow this a
function could access the variable b outside the function scope.
}
var b = 10;
a();
// CASE 2
function a() {
c();
function c() {
[Link](b); // 10
}
}
var b = 10;
a();
[Link] 10/82
12/09/2025, 21:19 title: Namaste JavaScript
// CASE 3
function a() {
c();
function c() {
var b = 100;
[Link](b); // 100
}
}
var b = 10;
a();
// CASE 4
function a() {
var b = 10;
c();
function c() {
[Link](b); // 10
}
}
a();
[Link](b); // Error, Not Defined
[Link] 11/82
12/09/2025, 21:19 title: Namaste JavaScript
So, Lexical Environment = local memory + lexical env of its parent. Hence, Lexical
Environement is the local memory along with the lexical environment of its parent
Lexical: In hierarchy, In order
Whenever an Execution Context is created, a Lexical environment(LE) is also created and is
referenced in the local Execution Context(in memory space).
The process of going one by one to parent and checking for values is called scope chain or
Lexcial environment chain.
function a() {
function c() {
// logic here
}
c(); // c is lexically inside a
} // a is lexically inside global execution
[Link] 12/82
12/09/2025, 21:19 title: Namaste JavaScript
Lexical or Static scope refers to the accessibility of variables, functions and object based
on physical location in source code.
Global {
Outer {
Inner
}
}
// Inner is surrounded by lexical scope of Outer
TLDR; An inner function can access variables which are in outer functions even if inner
function is nested deep. In any other case, a function can't access variables not in its
scope.
[Link] 13/82
12/09/2025, 21:19 title: Namaste JavaScript
It looks like let isn't hoisted, but it is, let's understand
Both a and b are actually initialized as undefined in hoisting stage. But var b is inside the
storage space of GLOBAL, and a is in a separate memory object called script, where it can
be accessed only after assigning some value to it first ie. one can access 'a' only if it is
assigned. Thus, it throws error.
Temporal Dead Zone : Time since when the let variable was hoisted until it is initialized
some value.
let a = 10;
let a = 100; //this code is rejected upfront as SyntaxError. (duplicate
declaration)
------------------
let a = 10;
var a = 100; // this code also rejected upfront as SyntaxError. (can't use
same name in same scope)
Let is a stricter version of var. Now, const is even more stricter than let.
let a;
a = 10;
[Link](a) // 10. Note declaration and assigning of a is in different
lines.
------------------
const b;
b = 10;
[Link](b); // SyntaxError: Missing initializer in const declaration.
(This type of declaration won't work with const. const b = 10 only will
work)
------------------
const b = 100;
b = 1000; //this gives us TypeError: Assignment to constant variable.
This Error signifies that x has never been in the scope of the program. This literally
means that x was never defined/declared and is being tried to be accesed.
Uncaught ReferenceError: cannot access 'a' before initialization
This Error signifies that 'a' cannot be accessed because it is declared as 'let' and
since it is not assigned a value, it is its Temporal Dead Zone. Thus, this error occurs.
Uncaught SyntaxError: Identifier 'a' has already been declared
This Error signifies that we are redeclaring a variable that is 'let' declared. No
execution will take place.
[Link] 14/82
12/09/2025, 21:19 title: Namaste JavaScript
Uncaught SyntaxError: Missing initializer in const declaration
Block aka compound statement is used to group JS statements together into 1 group. We
group them within {...}
[Link] 15/82
12/09/2025, 21:19 title: Namaste JavaScript
{
var a = 10;
let b = 20;
const c = 30;
// Here let and const are hoisted in Block scope,
// While, var is hoisted in Global scope.
}
{
var a = 10;
let b = 20;
const c = 30;
}
[Link](a); // 10
[Link](b); // Uncaught ReferenceError: b is not defined
* Reason?
* In the BLOCK SCOPE; we get b and c inside it initialized as
*undefined* as a part of hoisting (in a seperate memory space called
**block**)
* While, a is stored inside a GLOBAL scope.
* Thus we say, *let* and *const* are BLOCK SCOPED. They are stored in
a separate mem space which is reserved for this block. Also, they can't be
accessed outside this block. But var a can be accessed anywhere as it is
in global scope. Thus, we can't access them outside the Block.
What is Shadowing?
var a = 100;
{
var a = 10; // same name as global var
let b = 20;
const c = 30;
[Link](a); // 10
[Link](b); // 20
[Link](c); // 30
}
[Link](a); // 10, instead of the 100 we were expecting. So block "a"
modified val of global "a" as well. In console, only b and c are in block
space. a initially is in global space(a = 100), and when a = 10 line is
run, a is not created in block space, but replaces 100 with 10 in global
space itself.
So, If one has same named variable outside the block, the variable inside the block
shadows the outside variable. This happens only for var
Let's observe the behaviour in case of let and const and understand it's reason.
[Link] 16/82
12/09/2025, 21:19 title: Namaste JavaScript
let b = 100;
{
var a = 10;
let b = 20;
const c = 30;
[Link](b); // 20
}
[Link](b); // 100, Both b's are in separate spaces (one in Block(20)
and one in Script(another arbitrary mem space)(100)). Same is also true
for *const* declarations.
const c = 100;
function x() {
const c = 10;
[Link](c); // 10
}
x();
[Link](c); // 100
let a = 20;
{
var a = 20;
}
// Uncaught SyntaxError: Identifier 'a' has already been declared
We cannot shadow let with var. But it is valid to shadow a let using a let. However, we can
shadow var with let.
All scope rules that work in function are same in arrow functions too.
Since var is function scoped, it is not a problem with the code below.
[Link] 17/82
12/09/2025, 21:19 title: Namaste JavaScript
let a = 20;
function x() {
var a = 20;
}
Episode 10 : Closures in JS
Function bundled along with it's lexical scope is closure.
JavaScript has a lexcial scope environment. If a function needs to access a variable, it first
goes to its local memory. When it does not find it there, it goes to the memory of its lexical
parent. See Below code, Over here function y along with its lexical scope i.e. (function x)
would be called a closure.
function x() {
var a = 7;
function y() {
[Link](a);
}
return y;
}
var z = x();
[Link](z); // value of z is entire code of function y.
In above code, When y is returned, not only is the function returned but the entire
closure (fun y + its lexical scope) is returned and put inside z. So when z is used
somewhere else in program, it still remembers var a inside x()
[Link] 18/82
12/09/2025, 21:19 title: Namaste JavaScript
Another Example
function z() {
var b = 900;
function x() {
var a = 7;
function y() {
[Link](a, b);
}
y();
}
x();
}
z(); // 7 900
*A closure is a function that has access to its outer function scope even after the
function has returned. Meaning, A closure can remember and access variables and
arguments reference of its outer function even after the function has returned.*
Advantages of Closure:
Certainly! Let's explore examples for each of the advantages you've mentioned:
[Link] 19/82
12/09/2025, 21:19 title: Namaste JavaScript
// [Link]
const authModule = (function () {
let loggedInUser = null;
function logout() {
loggedInUser = null;
}
function getUserInfo() {
return loggedInUser;
}
return {
login,
logout,
getUserInfo,
};
})();
// Usage
[Link]('john_doe', 'secret');
[Link]([Link]()); // 'john_doe'
2. Currying:
3. Memoization:
Memoization optimizes expensive function calls by caching their results. It's useful
for recursive or repetitive computations.
Example: Implement a memoized Fibonacci function.
[Link](fibonacci(10)); // 55
[Link] 20/82
12/09/2025, 21:19 title: Namaste JavaScript
Encapsulation hides the internal details of an object and exposes only necessary
methods and properties. It improves code maintainability and security.
Example: Create a Person class with private properties.
class Person {
#name; // Private field
constructor(name) {
this.#name = name;
}
getName() {
return this.#name;
}
}
5. setTimeouts:
[Link] 21/82
12/09/2025, 21:19 title: Namaste JavaScript
function x() {
var i = 1;
setTimeout(function () {
[Link](i);
}, 3000);
[Link]("Namaste Javascript");
}
x();
// Output:
// Namaste Javascript
// 1 // after waiting 3 seconds
We expect JS to wait 3 sec, print 1 and then go down and print the string. But JS prints
string immediately, waits 3 sec and then prints 1.
The function inside setTimeout forms a closure (remembers reference to i). So wherever
function goes it carries this ref along with it.
setTimeout takes this callback function & attaches timer of 3000ms and stores it. Goes to
next line without waiting and prints string.
After 3000ms runs out, JS takes function, puts it into call stack and runs it.
Q: Print 1 after 1 sec, 2 after 2 sec till 5 : Tricky interview question
[Link] 22/82
12/09/2025, 21:19 title: Namaste JavaScript
function x() {
for (var i = 1; i <= 5; i++) {
setTimeout(function () {
[Link](i);
}, i * 1000);
}
[Link]("Namaste Javascript");
}
x();
// Output:
// Namaste Javascript
// 6
// 6
// 6
// 6
// 6
Reason?
This happens because of closures. When setTimeout stores the function somewhere
and attaches timer to it, the function remembers its reference to i, not value of i. All
5 copies of function point to same reference of i. JS stores these 5 functions, prints
string and then comes back to the functions. By then the timer has run fully. And
due to looping, the i value became 6. And when the callback fun runs the variable i =
6. So same 6 is printed in each log
To avoid this, we can use let instead of var as let has Block scope. For each
iteration, the i is a new variable altogether(new copy of i). Everytime setTimeout is
run, the inside function forms closure with new variable i
But what if interviewer ask us to implement using var?
function x() {
for (var i = 1; i <= 5; i++) {
function close(i) {
setTimeout(function () {
[Link](i);
}, i * 1000);
// put the setT function inside new function close()
}
close(i); // everytime you call close(i) it creates new copy of i. Only
this time, it is with var itself!
}
[Link]("Namaste Javascript");
}
x();
[Link] 23/82
12/09/2025, 21:19 title: Namaste JavaScript
function outer() {
var a = 10;
function inner() {
[Link](a);
} // inner forms a closure with outer
return inner;
}
outer()(); // 10 // over here first `()` will return inner function and
then using second `()` to call inner function
function outer() {
function inner() {
[Link](a);
}
var a = 10;
return inner;
}
outer()(); // 10
[Link] 24/82
12/09/2025, 21:19 title: Namaste JavaScript
Ans: Yes, because inner function forms a closure with its outer environment so sequence
doesn't matter.
function outer() {
let a = 10;
function inner() {
[Link](a);
}
return inner;
}
outer()(); // 10
Q4: Will inner function have the access to outer function argument?
function outer(str) {
let a = 10;
function inner() {
[Link](a, str);
}
return inner;
}
outer("Hello There")(); // 10 "Hello There"
Ans: Inner function will now form closure and will have access to both a and str.
function outest() {
var c = 20;
function outer(str) {
let a = 10;
function inner() {
[Link](a, c, str);
}
return inner;
}
return outer;
}
outest()("Hello There")(); // 10 20 "Hello There"
Ans: Yes, inner will have access to all its outer environment.
[Link] 25/82
12/09/2025, 21:19 title: Namaste JavaScript
function outest() {
var c = 20;
function outer(str) {
let a = 10;
function inner() {
[Link](a, c, str);
}
return inner;
}
return outer;
}
let a = 100;
outest()("Hello There")(); // 10 20 "Hello There"
Ans: Still the same output, the inner function will have reference to inner a, so conflicting
name won't matter here. If it wouldn't have find a inside outer function then it would have
went more outer to find a and thus have printed 100. So, it try to resolve variable in scope
chain and if a wouldn't have been found it would have given reference error.
[Link] 26/82
12/09/2025, 21:19 title: Namaste JavaScript
// without closures
var count = 0;
function increment(){
count++;
}
// in the above code, anyone can access count and change it.
------------------------------------------------------------------
------------------------------------------------------------------
*************************
// Above code is not good and scalable for say, when you plan to implement
decrement counter at a later stage.
// To address this issue, we use *constructors*
function a() {
var x = 0;
return function b() {
[Link](x);
};
}
[Link] 28/82
12/09/2025, 21:19 title: Namaste JavaScript
function a() {
[Link]("Hello");
}
a(); // Hello
var b = function () {
[Link]("Hello");
};
b();
function () {
They don't have their own identity. So an anonymous function without code inside it results
in an error.
Anonymous functions are used when functions are used as values eg. the code sample for
function expression above.
[Link] 29/82
12/09/2025, 21:19 title: Namaste JavaScript
Q: Parameters vs Arguments?
[Link] 30/82
12/09/2025, 21:19 title: Namaste JavaScript
setTimeout(function () {
[Link]("Timer");
}, 1000); // first argument is callback function and second is timer.
JS is a synchronous and single threaded language. But due to callbacks, we can do async
things in JS.
setTimeout(function () {
[Link]("timer");
}, 5000);
function x(y) {
[Link]("x");
y();
}
x(function y() {
[Link]("y");
});
// x y timer
[Link] 31/82
12/09/2025, 21:19 title: Namaste JavaScript
In the call stack, first x and y are present. After code execution, they go away and stack is
empty. Then after 5 seconds (from beginning) anonymous suddenly appear up in stack ie.
setTimeout
All 3 functions are executed through call stack. If any operation blocks the call stack, its
called blocking the main thread.
Say if x() takes 30 sec to run, then JS has to wait for it to finish as it has only 1 call stack/1
main thread. Never block main thread.
Always use async for functions that take time eg. setTimeout
Event Listener
We will create a button in html and attach event to it.
// [Link]
<button id="clickMe">Click Me!</button>;
// in [Link]
[Link]("clickMe").addEventListener("click", function
xyz() {
//when event click occurs, this callback function (xyz) is called into
callstack
[Link]("Button clicked");
});
let count = 0;
document
.getElementById("clickMe")
.addEventListener("click", function xyz() {
[Link]("Button clicked", ++count);
});
[Link] 32/82
12/09/2025, 21:19 title: Namaste JavaScript
function attachEventList() {
//creating new function for closure
let count = 0;
document
.getElementById("clickMe")
.addEventListener("click", function xyz() {
[Link]("Button clicked", ++count); //now callback function forms
closure with outer scope(count)
});
}
attachEventList();
[Link] 33/82
12/09/2025, 21:19 title: Namaste JavaScript
Browser has JS Engine which has Call Stack which has Global execution context, local
execution context etc.
But browser has many other superpowers - Local storage space, Timer, place to enter
URL, Bluetooth access, Geolocation access and so on.
Now JS needs some way to connect the callstack with all these superpowers. This is
done using Web APIs.
[Link] 34/82
12/09/2025, 21:19 title: Namaste JavaScript
WebAPIs
None of the below are part of Javascript! These are extra superpowers that browser has.
Browser gives access to JS callstack to use these powers.
setTimeout(), DOM APIs, fetch(), localstorage, console (yes, even [Link] is not JS!!),
location and so many more.
[Link] 35/82
12/09/2025, 21:19 title: Namaste JavaScript
[Link]("start");
setTimeout(function cb() {
[Link]("timer");
}, 5000);
[Link]("end");
// start end timer
cb() cannot simply directly go to callstack to be execeuted. It goes through the callback
queue when timer expires.
Event loop keep checking the callback queue, and see if it has any element to puts it into
call stack. It is like a gate keeper.
Once cb() is in callback queue, eventloop pushes it to callstack to run. Console API is used
and log printed
[Link] 36/82
12/09/2025, 21:19 title: Namaste JavaScript
See the below Image and code and try to understand the reason:
Explaination?
[Link]("Start");
[Link]("btn").addEventListener("click", function cb() {
// cb() registered inside webapi environment and event(click) attached to it.
i.e. REGISTERING CALLBACK AND ATTACHING EVENT TO IT.
[Link]("Callback");
});
[Link]("End"); // calls console api and logs in console window. After this
GEC get removed from call stack.
// In above code, even after console prints "Start" and "End" and pops GEC out,
the eventListener stays in webapi env(with hope that user may click it some day)
until explicitly removed, or the browser is closed.
Eventloop has just one job to keep checking callback queue and if found something push it
to call stack and delete from callback queue.
Ans: Suppose user clciks button x6 times. So 6 cb() are put inside callback queue. Event loop
sees if call stack is empty/has space and whether callback queue is not empty(6 elements
here). Elements of callback queue popped off, put in callstack, executed and then popped off
from call stack.
[Link] 37/82
12/09/2025, 21:19 title: Namaste JavaScript
Code Explaination:
* Same steps for everything before fetch() in above code.
* fetch registers cbF into webapi environment along with existing cbT.
* cbT is waiting for 5000ms to end so that it can be put inside callback
queue. cbF is waiting for data to be returned from Netflix servers gonna
take 2 seconds.
* After this millions of lines of code is running, by the time millions
line of code will execute, 5 seconds has finished and now the timer has
expired and response from Netflix server is ready.
* Data back from cbF ready to be executed gets stored into something
called a Microtask Queue.
* Also after expiration of timer, cbT is ready to execute in Callback
Queue.
* Microtask Queue is exactly same as Callback Queue, but it has higher
priority. Functions in Microtask Queue are executed earlier than Callback
Queue.
* In console, first Start and End are printed in console. First cbF goes
in callstack and "CB Netflix" is printed. cbF popped from callstack. Next
cbT is removed from callback Queue, put in Call Stack, "CB Timeout" is
printed, and cbT removed from callstack.
* See below Image for more understanding
[Link] 38/82
12/09/2025, 21:19 title: Namaste JavaScript
All the callback functions that come through promises go in microtask Queue.
Mutation Observer : Keeps on checking whether there is mutation in DOM tree or not, and
if there, then it execeutes some callback function.
Callback functions that come through promises and mutation observer go inside Microtask
Queue.
All the rest goes inside Callback Queue aka. Task Queue.
If the task in microtask Queue keeps creating new tasks in the queue, element in callback
queue never gets chance to be run. This is called starvation
1. When does the event loop actually start ? - Event loop, as the name suggests, is a
single-thread, loop that is almost infinite. It's always running and doing its job.
2. Are only asynchronous web api callbacks are registered in web api environment? -
YES, the synchronous callback functions like what we pass inside map, filter and reduce
aren't registered in the Web API environment. It's just those async callback functions
which go through all this.
3. Does the web API environment stores only the callback function and pushes the
same callback to queue/microtask queue? - Yes, the callback functions are stored, and
a reference is scheduled in the queues. Moreover, in the case of event listeners(for
example click handlers), the original callbacks stay in the web API environment forever,
that's why it's adviced to explicitly remove the listeners when not in use so that the
garbage collector does its job.
4. How does it matter if we delay for setTimeout would be 0ms. Then callback will
move to queue without any wait ? - No, there are trust issues with setTimeout() 😅 . The
callback function needs to wait until the Call Stack is empty. So the 0 ms callback might
have to wait for 100ms also if the stack is busy.
[Link] 39/82
12/09/2025, 21:19 title: Namaste JavaScript
[Link] 40/82
12/09/2025, 21:19 title: Namaste JavaScript
[Link] 41/82
12/09/2025, 21:19 title: Namaste JavaScript
[Link] 42/82
12/09/2025, 21:19 title: Namaste JavaScript
1. Parsing - Code is broken down into tokens. In "let a = 7" -> let, a, =, 7 are all tokens.
Also we have a syntax parser that takes code and converts it into an AST (Abstract
Syntax Tree) which is a JSON with all key values like type, start, end, body etc (looks
like [Link] but for a line of code in JS. Kinda unimportant)(Check out
[Link] -> converts line of code into AST).
2. Compilation - JS has something called Just-in-time(JIT) Compilation - uses both
interpreter & compiler. Also compilation and execution both go hand in hand. The AST
from previous step goes to interpreter which converts hi-level code to byte code and
moves to execeution. While interpreting, compiler also works hand in hand to compile
and form optimized code during runtime. Does JavaScript really Compiles? The
[Link] 43/82
12/09/2025, 21:19 title: Namaste JavaScript
answer is a loud YES. More info at: Link 1, Link 2, Link 3. JS used to be only interpreter
in old times, but now has both to compile and interpreter code and this make JS a JIT
compiled language, its like best of both world.
3. Execution - Needs 2 components ie. Memory heap(place where all memory is stored)
and Call Stack(same call stack from prev episodes). There is also a garbage collector. It
uses an algo called Mark and Sweep.
GiF Demo
Companies use different JS engines and each try to make theirs the best.
v8 of Google has Interpreter called Ignition, a compiler called Turbo Fan and garbage
collector called Orinoco
[Link] 44/82
12/09/2025, 21:19 title: Namaste JavaScript
v8 architecture:
[Link] 45/82
12/09/2025, 21:19 title: Namaste JavaScript
[Link]("Start");
setTimeout(function cb() {
[Link]("Callback");
}, 5000);
[Link]("End");
// Millions of lines of code to execute
// o/p: Over here setTimeout exactly doesn't guarantee that the callback
function will be called exactly after 5s. Maybe 6,7 or even 10! It all depends
on callstack. Why?
Reason?
[Link] 46/82
12/09/2025, 21:19 title: Namaste JavaScript
setTimeout guarantees that it will take at least the given timer to execute the code.
JS is a synchronous single threaded language. With just 1 thread it runs all pieces of code.
It becomes kind of an interpreter language, and runs code very fast inside browser (no need
to wait for code to be compiled) (JIT - Just in time compilation). And there are still ways to
do async operations as well.
What if timeout = 0sec?
[Link]("Start");
setTimeout(function cb() {
[Link]("Callback");
}, 0);
[Link]("End");
// Even though timer = 0s, the cb() has to go through the queue. Registers
calback in webapi's env , moves to callback queue, and execute once callstack is
empty.
// O/p - Start End Callback
// This method of putting timer = 0, can be used to defer a less imp function by
a little so the more important function(here printing "End") can take place
[Link] 47/82
12/09/2025, 21:19 title: Namaste JavaScript
function x() {
[Link]("Hi)";
};
function y(x) {
x();
};
y(); // Hi
// y is a higher order function
// x is a callback function
Let's try to understand how we should approach solution in interview. I have an array of
radius and I have to calculate area using these radius and store in an array.
First Approach:
The above solution works perfectly fine but what if we have now requirement to calculate
array of circumference. Code now be like
But over here we are violating some principle like DRY Principle, now lets observe the better
approach.
[Link] 48/82
12/09/2025, 21:19 title: Namaste JavaScript
Polyfill of map
// Over here calculate is nothing but polyfill of map function
// [Link]([Link](area)) == [Link](calculate(radiusArr,
area));
***************************************************
Lets convert above calculate function as map function and try to use. So,
[Link] = function(operation) {
const output = [];
for (let i = 0; i < [Link]; i++) {
[Link](operation(this[i]));
}
return output;
}
[Link]([Link](area))
[Link] 49/82
12/09/2025, 21:19 title: Namaste JavaScript
Map function
It is basically used to transform a array. The map() method creates a new array with the results
of calling a function for every array element.
const output = [Link](function) // this function tells map that what transformation I want on
each element of array
[Link] 50/82
12/09/2025, 21:19 title: Namaste JavaScript
So basically map function is mapping each and every value and transforming it based on
given condition.
Filter function
Filter function is basically used to filter the value inside an array. The [Link]() method is used
to create a new array from a given array consisting of only those elements from the given
array which satisfy a condition set by the argument method.
Filter function creates an array and store only those values which evaluates to true.
Reduce function
It is a function which take all the values of array and gives a single output of it. It reduces the
array to give a single output.
[Link] 51/82
12/09/2025, 21:19 title: Namaste JavaScript
// using reduce
const output = [Link]((acc, current) => {
if (current > acc ) {
acc = current;
}
return acc;
}, 0);
[Link](output); // 6
// acc is just a label which represent the accumulated value till now,
// so we can also label it as max in this case
const output = [Link]((max, current) => {
if (current > max) {
max= current;
}
return max;
}, 0);
[Link](output); // 6
Tricky MAP
[Link] 52/82
12/09/2025, 21:19 title: Namaste JavaScript
const users = [
{ firstName: "Alok", lastName: "Raj", age: 23 },
{ firstName: "Ashish", lastName: "Kumar", age: 29 },
{ firstName: "Ankit", lastName: "Roy", age: 29 },
{ firstName: "Pranav", lastName: "Mukherjee", age: 50 },
];
// Get array of full name : ["Alok Raj", "Ashish Kumar", ...]
const fullNameArr = [Link]((user) => [Link] + " " +
[Link]);
[Link](fullNameArr); // ["Alok Raj", "Ashish Kumar", ...]
----------------------------------------------------------
// Get the count/report of how many unique people with unique age are
there
// like: {29 : 2, 75 : 1, 50 : 1}
// We should use reduce, why? we want to deduce some information from the
array. Basically we want to get a single object as output
const report = [Link]((acc, curr) => {
if(acc[[Link]]) {
acc[[Link]] = ++ acc[[Link]] ;
} else {
acc[[Link]] = 1;
}
return acc; //to every time return update object
}, {})
[Link](report) // {29 : 2, 75 : 1, 50 : 1}
Function Chaining
// First name of all people whose age is less than 30
const users = [
{ firstName: "Alok", lastName: "Raj", age: 23 },
{ firstName: "Ashish", lastName: "Kumar", age: 29 },
{ firstName: "Ankit", lastName: "Roy", age: 29 },
{ firstName: "Pranav", lastName: "Mukherjee", age: 50 },
];
// function chaining
const output = users
.filter((user) => [Link] < 30)
.map((user) => [Link]);
[Link](output); // ["Alok", "Ashish", "Ankit"]
[Link] 53/82
12/09/2025, 21:19 title: Namaste JavaScript
Episode 20 : Callback
There are 2 Parts of Callback:
1. Good Part of callback - Callback are super important while writing asynchronous code
in JS
2. Bad Part of Callback - Using callback we can face issue:
Callback Hell
Inversion of control
Understanding of Bad part of callback is super important to learn Promise in next lecture.
[Link]("Namaste");
[Link]("JavaScript");
[Link]("Season 2");
// Namaste
// JavaScript
// Season 2
But what if we have to delay execution of any line, we could utilize callback, How?
[Link] 54/82
12/09/2025, 21:19 title: Namaste JavaScript
[Link]("Namaste");
setTimeout(function () {
[Link]("JavaScript");
}, 5000);
[Link]("Season 2");
// Namaste
// Season 2
// JavaScript
Assumption, once order is created then only we can proceed to payment, so there is a
dependency. So How to manage this dependency. Callback can come as rescue, How?
[Link](cart, function () {
[Link]();
});
// 💡 Over here `createOrder` api is first creating a order then it is
responsible to call `[Link]()` as part of callback approach.
To make it a bit complicated, what if after payment is done, you have to show Order summary
by calling [Link]() and now it has dependency on
[Link]() Now my code should look something like this:
[Link](cart, function () {
[Link](function () {
[Link]();
});
});
Now what if we have to update the wallet, now this will have a dependency over
showOrderSummary
[Link](cart, function () {
[Link](function () {
[Link](function () {
[Link]();
});
});
});
// 💡 Callback Hell
[Link] 55/82
12/09/2025, 21:19 title: Namaste JavaScript
When we have a large codebase and multiple apis and have dependency on each other, then
we fall into callback hell. These codes are tough to maintain. These callback hell structure is
also known as Pyramid of Doom.
Till this point we are comfortable with concept of callback hell but now lets discuss about
Inversion of Control . It is very important to understand in order to get comfortable around
the concept of promise.
💡 Inversion of control is like that you lose the control of code when we are using
callback.
[Link](cart, function () {
[Link]();
});
[Link] 56/82
12/09/2025, 21:19 title: Namaste JavaScript
Episode 21 : Promises
Promises are used to handle async operations in JavaScript.
We will discuss with code example that how things used to work before Promises and then
how it works after Promises
Now, we will make createOrder function return a promise and we will capture that promise
into a variable
Promise is nothing but we can assume it to be empty object with some data value in it, and
this data value will hold whatever this createOrder function will return.
[Link] 57/82
12/09/2025, 21:19 title: Namaste JavaScript
Since createOrder function is an async function and we don't know how much time will it
take to finish execution.
So the moment createOrder will get executed, it will return you a undefined value. Let's
say after 5 secs execution finished so now orderId is ready so, it will fill the undefined
value with the orderId .
In short, When createOrder get executed, it immediately returns a promise object with
undefined value. then javascript will continue to execute with other lines of code. After
sometime when createOrder has finished execution and orderId is ready then that will
automatically be assigned to our returned promise which was earlier undefined .
// {data: undefined}
// Initially it will be undefined so below code won't trigger
// After some time, when execution has finished and promiseRef has the
data then automatically the below line will get triggered.
[Link](function () {
proceedToPayment(orderId);
});
In Earlier solution we used to pass the function and then used to trust the function to execute
the callback.
There is difference between these words, passing a function and attaching a function.
Promise guarantee, it will callback the attached function once it has the fulfilled data. And it
will call it only once. Just once.
Earlier we talked about promise are object with empty data but that's not entirely true,
Promise are much more than that.
fetch is a web-api which is utilized to make api call and it returns a promise.
[Link] 58/82
12/09/2025, 21:19 title: Namaste JavaScript
/** OBSERVATIONS:
* If we will deep dive and see, this `promise` object has 3 things
* `prototype`, `promiseState` & `promiseResult`
* & this `promiseResult` is the same data which we talked earlier as data
* & initially `promiseResult` is `undefined`
*
* `promiseResult` will store data returned from API call
* `promiseState` will tell in which state the promise is currently,
initially it will be in `pending` state and later it will become
`fulfilled`
*/
/**
* When above line is executed, `fetch` makes API call and return a
`promise` instantly which is in `Pending` state and Javascript doesn't
wait to get it `fulfilled`
* And in next line it console out the `pending promise`.
* NOTE: chrome browser has some in-consistency, the moment console
happens it shows in pending state but if you will expand that it will show
fulfilled because chrome updated the log when promise get fulfilled.
* Once fulfilled data is there in promiseResult and it is inside body in
ReadableStream format and there is a way to extract data.
*/
Using .then
[Link](function (data) {
[Link](data);
});
// And this is how Promise is used.
// It guarantees that it could be resolved only once, either it could be
`success` or `failure`
/**
A Promise is in one of these states:
Interview Guide
💡
[Link] 59/82
12/09/2025, 21:19 title: Namaste JavaScript
💡 What is Promise?
-> Promise object is a placeholder for certain period of time until we receive value from
asynchronous operation.
We are now done solving one issue of callback i.e. Inversion of Control
// ⚠️ Common PitFall
// We forget to return promise in Promise Chaining
// The idea is promise/data returned from one .then become data for next
.then
// So,
createOrder(cart)
.then(function (orderId) {
return proceedToPayment(orderId);
})
.then(function (paymentInf) {
return showOrderSummary(paymentInf);
})
.then(function (balance) {
return updateWalletBalance(balance);
});
[Link] 60/82
12/09/2025, 21:19 title: Namaste JavaScript
[Link] 61/82
12/09/2025, 21:19 title: Namaste JavaScript
[Link](function (orderId) {
proceedToPayment(orderId);
});
Over above, if your validateCart is returning true, so the above promise will be resolved
(success),
[Link] 62/82
12/09/2025, 21:19 title: Namaste JavaScript
[Link](function (orderId) {
proceedToPayment(orderId);
});
function createOrder(cart) {
const promise = new Promise(function (resolve, reject) {
if (!validateCart(cart)) {
const err = new Error("Cart is not Valid");
reject(err);
}
const orderId = "12345";
if (orderId) {
resolve(orderId);
}
});
return promise;
}
Now let's see if there was some error and we are rejecting the promise, how we could catch
that?
-> Using .catch
[Link] 63/82
12/09/2025, 21:19 title: Namaste JavaScript
// Here we are consuming Promise and will try to catch promise error
promise
.then(function (orderId) {
// ✅ success aka resolved promise handling
proceedToPayment(orderId);
})
.catch(function (err) {
// ⚠️ failure aka reject handling
[Link](err);
});
[Link] 64/82
12/09/2025, 21:19 title: Namaste JavaScript
createOrder(cart)
.then(function (orderId) {
// ✅ success aka resolved promise handling
// 💡 we have return data or promise so that we can keep chaining the
promises, here we are returning data
[Link](orderId);
return orderId;
})
.then(function (orderId) {
// Promise chaining
// 💡 we will make sure that `proceedToPayment` returns a promise too
return proceedToPayment(orderId);
})
.then(function (paymentInfo) {
// from above, `proceedToPayment` is returning a promise so we can
consume using `.then`
[Link](paymentInfo);
})
.catch(function (err) {
// ⚠️ failure aka reject handling
[Link](err);
});
function proceedToPayment(cart) {
return new Promise(function (resolve, reject) {
// For time being, we are simply `resolving` promise
resolve("Payment Successful");
});
}
Q: What if we want to continue execution even if any of my promise is failing, how to achieve
this?
-> By placing the .catch block at some level after which we are not concerned with failure.
-> There could be multiple .catch too. Eg:
[Link] 65/82
12/09/2025, 21:19 title: Namaste JavaScript
createOrder(cart)
.then(function (orderId) {
// ✅ success aka resolved promise handling
// 💡 we have return data or promise so that we can keep chaining the
promises, here we are returning data
[Link](orderId);
return orderId;
})
.catch(function (err) {
// ⚠️ Whatever fails below it, catch wont care
// this block is responsible for code block above it.
[Link](err);
});
.then(function (orderId) {
// Promise chaining
// 💡 we will make sure that `proceedToPayment` returns a promise too
return proceedToPayment(orderId);
})
.then(function (paymentInfo) {
// from above, `proceedToPayment` is returning a promise so we can
consume using `.then`
[Link](paymentInfo);
})
What is async?
[Link] 66/82
12/09/2025, 21:19 title: Namaste JavaScript
What is await?
How async await works behind the scenes?
Example of using async/await
Error Handling
Interviews
Async await vs [Link]/.catch
Q: What is async?
A: Async is a keyword that is used before a function to create a async function.
// ❓ How to extract data from above promise? One way is using promise .then
[Link](res => [Link](res)); // Namaste JavaScript
But Question is how we used to handle promises earlier and why we even need async/await?
[Link] 67/82
12/09/2025, 21:19 title: Namaste JavaScript
function getData() {
[Link](res => [Link](res));
}
[Link] 68/82
12/09/2025, 21:19 title: Namaste JavaScript
// 📌 [Link]/.catch way
function getData() {
// JS engine will not wait for promise to be resolved
[Link](res => [Link](res));
[Link]('Hello There!');
}
getData(); // First `Hello There!` would be printed and then after 3 secs
'Promise resolved value!!' will be printed.
// Above happened as Javascript wait for none, so it will register this
promise and take this callback function and register separately then js
will move on and execute the following console and later once promise is
resolved, following console will be printed.
// ❓ Problem: Normally one used to get confused that JS will wait for
promise to be resolved before executing following lines.
// 📌 async-wait way:
async function handlePromise() {
// JS Engine will waiting for promise to resolve.
const val = await p;
[Link]('Hello There!');
[Link](val);
}
handlePromise(); // This time `Hello There!` won't be printed immediately
instead after 3 secs `Hello There!` will be printed followed by 'Promise
resolved value!!'
// 💡 So basically code was waiting at `await` line to get the promise
resolve before moving on to next line.
[Link] 69/82
12/09/2025, 21:19 title: Namaste JavaScript
// Let's create one promise and then resolve two different promise.
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise resolved value by p2!!');
}, 2000);
})
// Now let's reverse the order execution of promise and observe response.
async function handlePromise() {
[Link]('Hi');
const val = await p2;
[Link]('Hello There!');
[Link](val);
[Link] 70/82
12/09/2025, 21:19 title: Namaste JavaScript
// call stack flow -> handlePromise() is pushed -> It will log `Hi` to
console -> Next it sees we have await where promise is suppose to be
resolved -> So will it wait for promise to resolve and block call stack?
No -> thus handlePromise() execution get suspended and moved out of call
stack -> So when JS sees await keyword it suspend the execution of
function till promise is resolved -> So `p` will get resolved after 5 secs
so handlePromise() will be pushed to call-stack again after 5 secs. -> But
this time it will start executing from where it had left. -> Now it will
log 'Hello There!' and 'Promise resolved value!!' -> then it will check
whether `p2` is resolved or not -> It will find since `p2` will take 10
secs to resolve so the same above process will repeat -> execution will be
suspended until promise is resolved.
[Link] 71/82
12/09/2025, 21:19 title: Namaste JavaScript
Error Handling
While we were using normal Promise we were using .catch to handle error, now in
async-await we would be using try-catch block to handle error.
// In above whenever any error will occur the execution will move to catch
block. One could try above with bad url which will result in error.
[Link] 72/82
12/09/2025, 21:19 title: Namaste JavaScript
[Link]()
[Link]()
[Link]()
[Link]()
[Link]([p1, p2, p3]) -> Lets assume we are making 3 API call to fetch data. Also assume
p1 takes 3 seconds, p2 takes 1 second, p3 takes 2 seconds.
In first scenario let's assume all 3 promises are successful. So [Link] will take 3secs and
will give promise value of result like [val1, val2, val3]. It will wait for all of them to finish then it
will collect the results and give array as output.
[Link] 73/82
12/09/2025, 21:19 title: Namaste JavaScript
What if any of the promise gets rejected, for eg: [Link]([p1, p2, p3]). But this time, p2 get
rejected after 1 sec. Thus [Link] will throw same error as p2 immediately as soon as error
happened. It will not wait for other promise to either become success or failure. Moreover, p1
and p2 wont get cancelled as they are already triggered so it may result in success or failure
depending upon their fate but [Link] wont care. So its a situation of or/null.
💡 To conclude, the [Link]() waits for all the input promises to resolve and returns a new
promise that resolves to an array containing the results of the input promises. If one of the
input promises is rejected, the [Link]() method immediately returns a promise that is
rejected with an error of the first rejected promise.
[Link]()
[Link]() method that accepts a list of Promises and returns a new promise that
resolves after all the input promises have settled, either resolved or rejected.
[Link]([p1, p2, p3]) -> Lets assume we are making 3 API call to fetch data. Also
assume p1 takes 3 seconds, p2 takes 1 second, p3 takes 2 seconds.
In first scenario let's assume all 3 promises are successful. So [Link] will take
3secs and will give promise value of result like [val1, val2, val3]. It will wait for all of them to
finish then it will collect the results and give array as output.
What if any of the promise gets rejected, for eg: [Link]([p1, p2, p3]). But this time, p2 get
rejected after 1 sec. Thus [Link] will still wait for all promises to get settled. So
After 3 secs, it will be [val1, err, val3]
[Link]([p1, p2, p3]) -> Lets assume we are making 3 API call to fetch data. Also
assume p1 takes 3 seconds, p2 takes 1 second, p3 takes 2 seconds. So as soon as first
promise will resolve or reject, it will give the output.
So in Happy scenario, [Link] will give (val2) as output after 1sec as p2 got resolved at
the earliest. Whereas if it would have been failed [Link] would have still given output
after 1 sec but this time with error.
[Link]()
The [Link]() method accepts a list of Promise objects as an iterable object. If one of
the promises in the iterable object is fulfilled, the [Link]() returns a single promise
that resolves to a value which is the result of the fulfilled promise.
[Link]([p1, p2, p3]) -> Lets assume we are making 3 API call to fetch data. Also assume
p1 takes 3 seconds, p2 takes 1 second, p3 takes 2 seconds. So as soon as first promise will
be successful, it will give the output.
If in above situation what if p2 got rejected, nothing will happen as [Link] seek for
success, so the moment first success will happen that will become the result.
❓ But what if all promises got failed, so the returned result will be aggregated error i.e. [err1,
err2, err3].
[Link] 74/82
12/09/2025, 21:19 title: Namaste JavaScript
Code Examples:
[Link]()
// 📌 First Scenario
// 📌 Second Scenario
[Link]()
💡 This is safest among all Promises API.
[Link] 75/82
12/09/2025, 21:19 title: Namaste JavaScript
[Link]()
// 📌 First Scenario
[Link] 76/82
12/09/2025, 21:19 title: Namaste JavaScript
// 📌 Second Scenario
Notes:
Once promise is settled, it means -> got the result. Moreover, settled is broadly divided into
two categories:
[Link]()
// 📌 First Scenario
[Link] 77/82
12/09/2025, 21:19 title: Namaste JavaScript
// 📌 Second Scenario
// 📌 Third Scenario
Summary
There are 6 static methods of Promise class:
[Link](promises) – waits for all promises to resolve and returns an array of their
results. If any of the given promises rejects, it becomes the error of [Link], and all
other results are ignored.
[Link] 78/82
12/09/2025, 21:19 title: Namaste JavaScript
[Link](promises) (recently added method) – waits for all promises to settle and
returns their results as an array of objects with: status: "fulfilled" or "rejected" value (if
fulfilled) or reason (if rejected).
[Link](promises) – waits for the first promise to settle, and its result/error becomes
the outcome.
[Link](promises) (recently added method) – waits for the first promise to fulfill, and
its result becomes the outcome. If all of the given promises are rejected, AggregateError
becomes the error of [Link].
[Link](error) – makes a rejected promise with the given error. Of all these,
[Link] is probably the most common in practice.
[Link] 79/82
12/09/2025, 21:19 title: Namaste JavaScript
// On the first go feels like `this` keyword in global space and inside
function behaves same but in reality it's different.
// The moment you make JS run in strict mode by using: "use strict" at the
top, `this` keyword inside function returns `undefined` whereas global
space will still refers to global window object
this substitution -> According to this substitution, if the value of this keyword is
null/undefined , it will be replaced by globalObject only in non-strict mode. This is the
reason why this refers to global window object inside function in non-strict mode.
💡 So to summarize, the value of this keyword inside function is undefined , but because of
this substitution in non-strict mode this keyword refers to globalWindowObject and in
strict mode it will still be undefined
this keyword value depends on how the function is called. For eg:
In strict mode:
x(); // undefined
window.x(); // global window object
[Link] 80/82
12/09/2025, 21:19 title: Namaste JavaScript
const student = {
name: 'Alok',
printName: function () {
[Link]([Link]);
}
}
[Link](); // Alok
const student2 = {
name: 'Kajal',
}
[Link](); // throw error
// So, call, bind and apply is used to set the value of this keyword.
const obj = {
a: 10,
x: () => {
[Link](this); // window object
// Above the value of `this` won't be obj anymore instead it will
be enclosing lexical context i.e. window object in current scenario.
}
}
obj.x();
const obj2 = {
a: 10,
x: function () {
const y = () => {
[Link](this);
// Above the value of `this` will be obj2 as function y's
enclosing lexical context is function `x`.
};
y();
}
}
obj2.x();
[Link] 81/82
12/09/2025, 21:19 title: Namaste JavaScript
To Be Continued...
[Link] 82/82