JavaScript Behind the Scenes
JavaScript is a single-threaded, non-blocking, asynchronous programming language. Let's explore how it works under the hood.
Execution Context
When JavaScript code runs, it creates an execution context which has two phases:
// Creation Phase Example
console.log(name); // undefined (hoisting)
var name = "JavaScript";
// Execution Phase Example
function greet() {
console.log("Hello " + name);
}
greet(); // "Hello JavaScript"
Creation Phase
- Creates Global/Function Execution Context
- Sets up Memory Space (Variable Hoisting)
- Creates Scope Chain
- Sets
this
value
Execution Phase
- Executes code line by line
- Assigns values to variables
- Executes function calls
Call Stack
function first() {
console.log("First");
second();
}
function second() {
console.log("Second");
third();
}
function third() {
console.log("Third");
}
first();
// Call Stack:
// 1. first()
// 2. second()
// 3. third()
Event loop
JavaScript uses an event loop to handle asynchronous operations:
console.log("Start");
setTimeout(() => {
console.log("Timeout");
}, 0);
Promise.resolve().then(() => {
console.log("Promise");
});
console.log("End");
// Output:
// Start
// End
// Promise
// Timeout
The event loop follows this order:
- Synchronous code first
- Microtasks (Promises) next
- Macrotasks (setTimeout, setInterval) last
Memory Management
JavaScript automatically manages memory through garbage collection:
let user = {
name: "John",
};
user = null; // Object becomes eligible for garbage collection
Key concepts:
- Mark and Sweep Algorithm
- Reference Counting
- Memory Leaks Prevention
Scope and Closures
JavaScript uses lexical scoping and closures:
function outer() {
let count = 0;
return function inner() {
return count++;
};
}
const counter = outer();
console.log(counter()); // 0
console.log(counter()); // 1
Prototypes and Inheritance
JavaScript uses prototypal inheritance:
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function () {
return `${this.name} makes a sound`;
};
const dog = new Animal("Rex");
console.log(dog.speak()); // "Rex makes a sound"
Key Takeaways
- JavaScript is single-threaded but handles async operations via the event loop
- Every piece of code runs in an execution context
- Memory is managed automatically through garbage collection
- Scope determines variable accessibility
- Prototypes enable inheritance
Understanding these concepts helps write more efficient and maintainable JavaScript code.