JavaScript Fundamentals : Exercises
π Table of Contents:
π Closures
function outer() {
let count = 0;
return function inner() {
count++;
return count;
};
}
const createCounter = outer();
console.log(createCounter()); // 1
console.log(createCounter()); // 2
✅ inner() still has access to variable count, even though outer() has finished running.
πΉvar declaration in loops inside Closures
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Prints 3, 3, 3
✅ Use let to avoid this:
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Prints 0, 1, 2
π Hoisting
πΉvar Hoisting
console.log(x); // undefined
var x = 5;
Actual Flow:
var x; // Declaration hoisted
console.log(x); // undefined
x = 5; // Assignment happens later
πΉlet and const Hoisting
console.log(y); // ❌ ReferenceError
let y = 10;
πΉFunction Declarations Hoisting
sayHi(); // ✅ Works
function sayHi() {
console.log("Hi!");
}
Hoisted completely — both declaration and definition
πΉFunction Expressions Hoisting
sayHi(); // ❌ TypeError
var sayHi = function () {
console.log("Hi!");
};
Only declaration hoisted - considered as variable
π Scoping
πΉvar, let & const
let z = 4;// Global Scope
function test() {
var x = 3; // Function Scope
if (true) {
var x = 1; // Function Scope
let y = 2; // Block Scope
}
console.log(x); // 1
console.log(y); //❌ ReferenceError
}
console.log(z); // 4
π Promises
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Data loaded');
}, 1000);
});
};fetchData().then((data) => console.log(data)).catch((error) => console.log(error);
π Async/Await
async function loadData() {console.log('Fetching...');const data = await fetchData(); //pausesconsole.log(data);}
π Event Loop
console.log("Start");setTimeout(() => {console.log("Macrotask");}, 0);Promise.resolve().then(() => {console.log("Microtask");});console.log("End");
order of execution
// Start
// End
// Microtask
// Macrotask
π this
const user = {name: 'User1',sayHi() {setTimeout(function () {console.log(`Hi, I'm ${this.name}`);}, 1000);}};user.sayHi(); // ❌ undefined
✅ Fix it with bind:setTimeout(function () {console.log(`Hi, I'm ${this.name}`); // Hi, I'm User1}.bind(this), 1000);✅ Or use an arrow function:setTimeout(() => {console.log(`Hi, I'm ${this.name}`); // Hi, I'm User1}, 1000);Arrow functions don’t bind their own this—they inherit it from the outer context.
π call, apply & bind
function greet(city) {
console.log(`Hi, I'm ${this.name} from ${city}`);
}
const person = { name: 'User1' };
π Using call
greet.call(person, 'Berlin'); // "Hi, I'm User1 from Berlin"
π Using apply
greet.apply(person, ['Berlin']); // "Hi, I'm User1 from Berlin"
π Using bind
const boundGreet = greet.bind(person, 'Berlin');
boundGreet(); // "Hi, I'm User1 from Berlin"
π stack, heap, GC
let heapObject = null;
function simulateStackHeap() {
// === Stack Allocation (local variables) ===
const number = 42; // Primitive → stack
const message = "Hello, stack!"; // Primitive → stack
// === Heap Allocation ===
heapObject = {
data: new Array(1_000_000).fill("heap memory"),
};
console.log("Stack values:", number, message);
console.log("Heap object allocated.");
}
function releaseHeap() {
heapObject = null; // Dereference to allow GC
console.log("Heap object released. Wait for GC.");
}
Stick around — I’ll keep adding practical bits here as we roll out more of the JavaScript Series >>>
Comments
Post a Comment
Enter you valuable comments