Skip to content

Add "JavaScript behind the scenes" section with key concepts #217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions en/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@
- [Velocity JS](animation-resources/velocityjs.md)
- [React Spring](animation-resources/react-spring.md)
- [Framer Motion](animation-resources/framer-motion.md)
- [JavaScript Behind the Scenes](behind-scenes/README.md)
- [Call Stack](behind-scenes/call-stack.md)
- [Engine](behind-scenes/engine.md)
- [Event Loop](behind-scenes/event-loop.md)
- [References](References.md)
- [Resources](resources.md)
- [Credits](Credits.md)
47 changes: 47 additions & 0 deletions en/behind-scenes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
layout: editorial
chapter: 27
pageNumber: 256
description: JavaScript behind the scenes.
---

## JavaScript Behind the Scenes

JavaScript is a versatile language that runs in various environments, including browsers and servers. Understanding how
JavaScript works behind the scenes can help you write more efficient and effective code. This guide covers key concepts
such as the JavaScript engine, execution context, call stack, memory heap, runtime environment, and event loop.

### JavaScript Engine

A JavaScript engine is a program or interpreter that executes JavaScript code. Popular engines like V8 (used in Google
Chrome and Node.js), SpiderMonkey (used in Firefox), and JavaScriptCore (used in Safari) parse the code into an Abstract
Syntax Tree (AST), compile it into bytecode or machine code, and then execute it.

### Execution Context

An execution context is an environment where JavaScript code is evaluated and executed. There are three types: global,
function, and eval. Each context has a creation phase, where variables, functions, and the `this` keyword are created,
and an execution phase, where the code is executed line by line.

### Call Stack

The call stack is a data structure that keeps track of function calls in a Last-In, First-Out (LIFO) manner. It helps
the JavaScript engine manage the execution of multiple functions by pushing and popping function calls as they are
invoked and completed.

### Memory Heap

The memory heap is a region in memory where objects are stored. JavaScript uses garbage collection to manage memory,
automatically freeing up memory that is no longer in use, thus preventing memory leaks and optimizing performance.

### Runtime Environment

The runtime environment provides the necessary resources for JavaScript to execute. In a browser, this includes the
Document Object Model (DOM), Web APIs, and the JavaScript engine. In Node.js, it includes the file system, HTTP module,
and other Node.js-specific APIs.

### Event Loop

The event loop allows JavaScript to perform non-blocking operations by offloading tasks to the system kernel whenever
possible. It continuously checks the call stack and processes the callback queue, enabling asynchronous programming and
efficient execution of code.
75 changes: 75 additions & 0 deletions en/behind-scenes/call-stack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
chapter: 27
pageNumber: 257
description: Understanding Call Stacks in JavaScript
---


## Understanding Call Stacks in JavaScript

In JavaScript, a Call Stack is a data structure that uses the Last-In, First-Out (LIFO) principle to temporarily store and manage function invocation (call).

### What is a Call Stack?

A call stack is responsible for keeping track of function calls in your code. The call stack helps the JavaScript interpreter to keep track of what function is currently being run and what functions are called from within that function, and so on.

When a script calls a function, JavaScript's interpreter adds that function to the call stack and then starts carrying out the function. Any functions that are called by that function are added to the call stack further up, and run where their calls are reached.

When the current function is finished, the interpreter takes it off the stack and resumes execution where it left off in the last line of code that was run.

### Example of a Call Stack

Here's a basic example to understand how a call stack works:

```javascript
function firstFunction() {
console.log("First function is called.");
secondFunction();
console.log("First function is done.");
}

function secondFunction() {
console.log("Second function is called.");
thirdFunction();
console.log("Second function is done.");
}

function thirdFunction() {
console.log("Third function is called.");
}

firstFunction();
```

**Output:**
```
First function is called.
Second function is called.
Third function is called.
Second function is done.
First function is done.
```

### How the Call Stack Works

1. When `firstFunction` is called, it is added to the call stack.
2. Inside `firstFunction`, `secondFunction` is called, so it is added to the call stack.
3. Inside `secondFunction`, `thirdFunction` is called, so it is added to the call stack.
4. `thirdFunction` completes and is removed from the call stack.
5. `secondFunction` resumes, completes, and is removed from the call stack.
6. `firstFunction` resumes, completes, and is removed from the call stack.

### Stack Overflow

A stack overflow occurs when there are too many function calls in the call stack. This can happen with recursive functions that do not have a base case to stop the recursion.

```javascript
function recursiveFunction() {
recursiveFunction();
}

recursiveFunction();
```

This will result in a "Maximum call stack size exceeded" error.

92 changes: 92 additions & 0 deletions en/behind-scenes/engine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
chapter: 27
pageNumber: 258
description: Understanding JavaScript Engines and how they execute JavaScript code.
---

## Understanding JavaScript Engines

A JavaScript engine is a program or an interpreter that executes JavaScript code. The most well-known JavaScript engines are V8 (used in Google Chrome and Node.js), SpiderMonkey (used in Firefox), and JavaScriptCore (used in Safari).

### How JavaScript Engines Work

JavaScript engines perform several key tasks to execute JavaScript code efficiently:

1. **Parsing**: The engine parses the JavaScript code into an Abstract Syntax Tree (AST).
2. **Compilation**: The AST is then compiled into bytecode or machine code.
3. **Execution**: The compiled code is executed by the engine.

### Example of JavaScript Engine Workflow

Here's a simple example to illustrate the workflow of a JavaScript engine:

```javascript
function add(a, b) {
return a + b;
}

console.log(add(2, 3)); // Output: 5
```

### Parsing

The engine first parses the code into an AST. For the above code, the AST might look something like this:

```
Program
├── FunctionDeclaration (add)
│ ├── Identifier (a)
│ ├── Identifier (b)
│ └── BlockStatement
│ └── ReturnStatement
│ └── BinaryExpression (+)
│ ├── Identifier (a)
│ └── Identifier (b)
└── ExpressionStatement
└── CallExpression (console.log)
└── CallExpression (add)
├── Literal (2)
└── Literal (3)
```

### Compilation

The AST is then compiled into bytecode or machine code. This step involves optimizations to improve performance.

### Execution

The compiled code is executed by the engine. In this case, the `add` function is called with arguments `2` and `3`, and the result `5` is logged to the console.

### Just-In-Time (JIT) Compilation

Modern JavaScript engines use Just-In-Time (JIT) compilation to improve performance. JIT compilation involves compiling code at runtime, rather than before execution. This allows the engine to optimize the code based on actual usage patterns.

### Example of JIT Compilation

```javascript
function multiply(a, b) {
return a * b;
}

for (let i = 0; i < 1000000; i++) {
multiply(2, 3);
}
```

In this example, the `multiply` function is called repeatedly. A JIT compiler can optimize the function after detecting that it is a hot function (i.e., frequently called).

### Garbage Collection

JavaScript engines also include garbage collectors to manage memory. The garbage collector automatically frees up memory that is no longer in use, preventing memory leaks.

### Example of Garbage Collection

```javascript
function createObject() {
return { name: "Object" };
}

let obj = createObject();
obj = null; // The object is now eligible for garbage collection
```
In this example, the object created by `createObject` is eligible for garbage collection after `obj` is set to `null`.
132 changes: 132 additions & 0 deletions en/behind-scenes/event-loop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
---
chapter: 27
pageNumber: 259
description: Understanding the Event Loop in JavaScript.
---

## Understanding the Event Loop in JavaScript

The event loop is a fundamental concept in JavaScript that allows for asynchronous programming. It is responsible for executing code, collecting and processing events, and executing queued sub-tasks.

### How the Event Loop Works

JavaScript is single-threaded, meaning it can execute one piece of code at a time. The event loop allows JavaScript to perform non-blocking operations by offloading operations to the system kernel whenever possible.

### Components of the Event Loop

1. **Call Stack**: The call stack is where the JavaScript engine keeps track of function calls.
2. **Web APIs**: These are provided by the browser (or Node.js) and include things like `setTimeout`, `DOM events`, and `HTTP requests`.
3. **Callback Queue**: This is where functions are queued up to be executed after the call stack is clear.
4. **Event Loop**: The event loop continuously checks the call stack to see if it's empty. If it is, it takes the first event from the callback queue and pushes it to the call stack.

### Example of the Event Loop

Here's a simple example to illustrate how the event loop works:

```javascript
console.log("Start");

setTimeout(() => {
console.log("Timeout");
}, 0);

console.log("End");
```

**Output:**
```
Start
End
Timeout
```

### Explanation

1. `console.log("Start")` is executed and "Start" is printed.
2. `setTimeout` is called, and the callback is sent to the Web API. The main thread continues.
3. `console.log("End")` is executed and "End" is printed.
4. The event loop checks the call stack and finds it empty. It then pushes the `setTimeout` callback to the call stack.
5. The `setTimeout` callback is executed and "Timeout" is printed.

### Event Loop in Action

Here's a more complex example to demonstrate the event loop in action:

```javascript
console.log("Start");

setTimeout(() => {
console.log("Timeout 1");
}, 1000);

setTimeout(() => {
console.log("Timeout 2");
}, 0);

Promise.resolve().then(() => {
console.log("Promise");
});

console.log("End");
```

**Output:**
```
Start
End
Promise
Timeout 2
Timeout 1
```

### Explanation

1. `console.log("Start")` is executed and "Start" is printed.
2. `setTimeout` with 1000ms delay is called and the callback is sent to the Web API.
3. `setTimeout` with 0ms delay is called and the callback is sent to the Web API.
4. `Promise.resolve().then` is called and the callback is sent to the microtask queue.
5. `console.log("End")` is executed and "End" is printed.
6. The event loop checks the call stack and finds it empty. It then processes the microtask queue first, executing the `Promise` callback and printing "Promise".
7. The event loop then processes the callback queue, executing the `setTimeout` with 0ms delay and printing "Timeout 2".
8. Finally, the `setTimeout` with 1000ms delay is executed and "Timeout 1" is printed.

### Microtasks vs Macrotasks

Microtasks (e.g., Promises) have higher priority than macrotasks (e.g., `setTimeout`). The event loop processes all microtasks before moving on to the next macrotask.

### Example of Microtasks and Macrotasks

```javascript
console.log("Start");

setTimeout(() => {
console.log("Timeout");
}, 0);

Promise.resolve().then(() => {
console.log("Promise 1");
}).then(() => {
console.log("Promise 2");
});

console.log("End");
```

**Output:**
```
Start
End
Promise 1
Promise 2
Timeout
```

### Explanation

1. `console.log("Start")` is executed and "Start" is printed.
2. `setTimeout` is called and the callback is sent to the Web API.
3. `Promise.resolve().then` is called and the callback is sent to the microtask queue.
4. `console.log("End")` is executed and "End" is printed.
5. The event loop processes the microtask queue, executing the `Promise` callbacks and printing "Promise 1" and "Promise 2".
6. The event loop then processes the callback queue, executing the `setTimeout` callback and printing "Timeout".

Loading