ABOUT JAVASCRIPT

JavaScript properties -
1. High level - In JS, we don't have to manage memory. It is automatically done by the computer.

2. Garbage-Collected - It automatically cleans up unused memory.

3. Interpreted or just-in-time compiled - First the whole code gets compiled inside the JS engine and then it gets executed.

4. Multi-paradigm -
a) Procedural programming
b) Object-oriented programming
c) Functional programming

5. Prototype-based object-oriented - Almost everything in JS is objects except for primitive datatypes such as numbers, booleans.

6. First class functions - This simply means that functions are just treated as values. We can pass them into other functions and return them from functions.

7. Dynamically typed - Variable types are not defined while declaring them, they become known only during the runtime. Datatype of variable is automatically changed.

8. Single-thread

9. Non-blocking event loop

COMPILATION VS INTERPRETATION VS JUST-IN-TIME (JIT) COMPILATION

1. Compilation - Entire code is coverted to machine code at once, and written to a binary file that can be later executed by the computer.
2. Interpretation - Interpreter runs through the source code and executes it line by line.
3. Just-in-time compilation - Entire code is converted to machine code at once and then is executed immediately.

JavaScript Engine = Call Stack + Memory Heap
Top level code - Code in the global scope that is NOT inside any function.

EXECUTION CONTEXT

Environment in which a piece of JS code is executed. It stores all the necessary information for some code to be executed. Execution context is the pizza box where we eat the pizza.
It contains -
1. Variable Environment It contains -
a) let, const and var declarations
b) Function declarations
c) argument objects
2. Scope Chain
3. this keyword
NOTE - Arrow functions do not contain argument object and this keyword.

HOW EXECUTION OF JS CODE HAPPENS

1. Creation of GLOBAL EXECUTION CONTEXT for top level code.
2. Execution of top-level code (inside Global execution context).
3. Execution of functions and waiting for callbacks (For each function call, a new execution context is created).

Call Stack = All the execution context together.
Call Stack is a "place" where execution contexts get stacked on top of each other, to keep track of where we are in the execution process.
In the call stack, once a function is CALLED inside the JS code, it's execution context is created, once that function gets executed then only the EC below gets executed.
For each function call a new EC gets stacked in the call stack and gets executed first, unless it has a function call inside it to another function.

SCOPING/SCOPE CHAIN

Scope - Environment in which a certain variable is available. There are
1. Global scope
2. Function/local scope
3. Block scope - Variables are accessible only inside block (if block, for loop block, etc). This only applies to let and const variables.

let and const are block-scoped and var is function-scoped.

NOTE - In strict mode, functions are also block scoped, this means, a function defined inside a code block is accessible inside that block only.

Lexical Scoping - Scoping is controlled by the placement of functions and blocks in the code.
JS looks for variables first inside the current scope and then outside the current scope. If a variable with the same name exists inside the current scope as well as outside it, then the one in the current scope will be used.

HOISTING

Hoisting - Makes some types of variable accessible/usable in the code before they are actually declared. Variables are lifted to the top of their scope.
Before execution, code is scanned for variable declarations, and for each variable, a new property is created in the VARIABLE ENVIRONMENT OBJECT.
Only function declarations and variables declared with var are hoisted.
Variables declared with var have an initial value of "undefined".

Temporal Dead Zone -
It's basically the region of the scope in which the variable is defined, but can't be used in any way. So it is as if the variable didn't even exist.
Each and every let and const variable get their own Temporal Dead Zone that starts at the beginning of the scope until the line where it is defined. The variable is only safe to use after the TDZ.

THIS KEYWORD

-> "this" keyword is basically a special variable that is created for every execution context and therefore every function.​
It will always take the value of the owner of the function in which, the this keyword is used.​
The value of the "this" keyword is not static. It's not always the same. It depends on how the function is actually called. And its value is only assigned when the function is actually called.​

This keyword points to -
1. In case of methods - Object that is calling the method
2. In case of simple function call - undefined (only in strict mode, otherwise it points to window object)
3. In case of Arrow functions - this of surrounding function/parent scope (lexical this)
4. In case of Event listener - DOM element that the handler is attached to
If we console.log(this); We will get the window object. It is the parent object of the global scope.

FOUR DIFFERENT WAYS IN WHICH FUNCTIONS CAN BE CALLED AND WHERE "THIS" KEYWORD POINTS IN EACH CASE

1. Calling a function as an object method:
Here, "this" = Object that is CALLING the method.
When we call a method, the this keyword inside that method will simply point to the object on which the method is called.​
Examples -

2. Simply calling function as a normal function:
Here, "this" = undefined​​
However, that is only valid for strict mode. So if you're not in strict mode, this will actually point to the global object,​ which in case of the browser is the window object.
Example -

3. Arrow functions
Here, "this" = "this" of parent function (lexical this)
Arrow functions do not get their own "this" keyword. Instead, if you use the "this" keyword in an arrow function,it will simply be the "this" keyword of the surrounding function which is the parent function. In technical terms, this is called the 'lexical "this" keyword'.

4. Event listener "this"
Here, "this" = DOM element that the handler is attached to
If a function is called as an event listener, then the this keyword will always point to the DOM element that the handler function is attached to.
The "this" keyword points to the window object in three cases:
a. if the "this" keyword is outside of any function (just outside in global scope) Example -

b. If the lexical scope (parent scope) of arrow function is global scope
Example -

c. In case of regular function if you are not using strict mode
Example -

NEVER USE ARROW FUNCTIONS TO DEFINE OBJECT METHODS

ARROW FUNCTIONS VS NORMAL FUNCTIONS

PRIMITIVES VS REFERENCE TYPES

Primitive types are stored in the call stack. Reference types are stored in the memory heap.

when we declare a variable as an object, an identifier is created, which points to a piece of memory in the call stack, which in turn points to a piece of memory in the memory heap. And that is where the object is actually stored. And it works this way because objects might be too large to be stored in the stack. Instead they are stored in the heap, which is like an almost unlimited memory pool. And the stack just keeps a reference to where the object is actually stored in the heap so that it can find it whenever necessary. NOTE - piece of memory = memory address

Check out the image below.

SOMETHING COOL