0% found this document useful (0 votes)
8 views8 pages

Js Hoisting Closures Real World

The document discusses the concepts of hoisting and closures in JavaScript, providing real-world use cases such as private variables in bank account modules, memoization for caching results, and event handlers with preserved context. It also addresses common interview questions related to closures, including closure in loops and module pattern implementation. Key takeaways emphasize the importance of understanding closures for data privacy, the pitfalls of hoisting, and the preference for using 'let' and 'const' over 'var'.

Uploaded by

noxiousrocco
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views8 pages

Js Hoisting Closures Real World

The document discusses the concepts of hoisting and closures in JavaScript, providing real-world use cases such as private variables in bank account modules, memoization for caching results, and event handlers with preserved context. It also addresses common interview questions related to closures, including closure in loops and module pattern implementation. Key takeaways emphasize the importance of understanding closures for data privacy, the pitfalls of hoisting, and the preference for using 'let' and 'const' over 'var'.

Uploaded by

noxiousrocco
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

Hoisting and Closures:

Real-World Scenarios
Real-World Use Cases of Closures
1. Private Variables and Encapsulation
// Real-world: Creating a secure bank account module
function createBankAccount(initialBalance) {
let balance = initialBalance; // Private variable
let transactions = []; // Private transaction log

return {
deposit(amount) {
if (amount > 0) {
balance += amount;
transactions.push({ type: 'deposit', amount, timestamp: new Date() });
return balance;
}
throw new Error('Deposit amount must be positive');
},
withdraw(amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
transactions.push({ type: 'withdrawal', amount, timestamp: new Date() });
return balance;
}
throw new Error('Insufficient funds or invalid amount');
},
getBalance() {
return balance;
},
getTransactionHistory() {
// Returns a copy to prevent direct manipulation
return [...transactions];
}
};
}

const myAccount = createBankAccount(1000);


myAccount.deposit(500); // 1500
myAccount.withdraw(200); // 1300
console.log(myAccount.getBalance()); // 1300
// Cannot directly access 'balance' or 'transactions'

2. Memoization (Caching Function Results)


// Real-world: Expensive Calculation Caching
function expensiveCalculation(n) {
console.log(`Calculating for ${n}`);
return n * n * n;
}

function memoize(fn) {
const cache = new Map();

return function(arg) {
if (cache.has(arg)) {
console.log(`Returning cached result for ${arg}`);
return cache.get(arg);
}
const result = fn(arg);
cache.set(arg, result);
return result;
};
}

const memoizedCalc = memoize(expensiveCalculation);


console.log(memoizedCalc(5)); // First call: calculates and caches
console.log(memoizedCalc(5)); // Second call: returns cached result

3. Event Handlers and Callback Preservation


// Real-world: Creating unique event listeners with preserved context
function setupButtonCounter(buttonId) {
let count = 0;
const button = document.getElementById(buttonId);

return function() {
count++;
console.log(`Button ${buttonId} clicked ${count} times`);
// Each button maintains its own independent count
};
}

const button1Handler = setupButtonCounter('btn1');


const button2Handler = setupButtonCounter('btn2');

document.getElementById('btn1').addEventListener('click', button1Handler);
document.getElementById('btn2').addEventListener('click', button2Handler);

Common Interview Questions on


Closures
1. Closure in a Loop
// Interview Question: Fix the closure in a loop problem
function createFunctions() {
let result = [];

// Problematic Version
for (var i = 0; i < 3; i++) {
result.push(function() {
console.log(i); // What will this print?
});
}

return result;
}

const functions = createFunctions();


functions[0](); // Prints 3
functions[1](); // Prints 3
functions[2](); // Prints 3

// Correct Solutions:
// Solution 1: Using let (block-scoped)
function createFunctionsFixed1() {
let result = [];

for (let i = 0; i < 3; i++) {


result.push(function() {
console.log(i); // Prints 0, 1, 2
});
}

return result;
}

// Solution 2: Using IIFE (Immediately Invoked Function Expression)


function createFunctionsFixed2() {
let result = [];

for (var i = 0; i < 3; i++) {


(function(j) {
result.push(function() {
console.log(j); // Prints 0, 1, 2
});
})(i);
}
return result;
}

2. Module Pattern Implementation

// Interview Question: Create a module with private and public methods


const counterModule = (function() {
// Private variables and methods
let count = 0;

function privateMethod() {
console.log('Internal count:', count);
}

// Public interface
return {
increment() {
count++;
privateMethod();
return count;
},
decrement() {
count--;
privateMethod();
return count;
},
getCount() {
return count;
}
};
})();

console.log(counterModule.increment()); // 1
console.log(counterModule.increment()); // 2
console.log(counterModule.getCount()); // 2
// count is not directly accessible

Hoisting Edge Cases and Gotchas


1. Function Declaration vs Function Expression
// Edge Case: Different hoisting behaviors
console.log(declaredFunc); // Function is fully hoisted
function declaredFunc() {
console.log("I'm a function declaration");
}

console.log(expressedFunc); // Throws TypeError


var expressedFunc = function() {
console.log("I'm a function expression");
};

// Function Declaration in Conditional Blocks (Avoid!)


if (true) {
function riskyFunc() {
console.log("This behaves differently across browsers");
}
}

2. Temporal Dead Zone with let/const

// Edge Case: Temporal Dead Zone


{
// console.log(x); // ReferenceError
// console.log(y); // ReferenceError

let x = 10;
const y = 20;

console.log(x); // 10
console.log(y); // 20
}

Interview Strategy
Closure Interview Preparation
1. Understand closure mechanism
2. Practice creating closures
3. Recognize common patterns
4. Be able to explain privacy and state preservation
Hoisting Interview Preparation
1. Know the difference between var, let, const
2. Understand function hoisting rules
3. Recognize potential pitfalls
4. Demonstrate ability to write clean, predictable code

Key Takeaways
Closures are powerful for data privacy and state management
Hoisting can lead to unexpected behaviors
Always prefer let and const over var
Understand scope and execution context

Practice Challenges
1. Implement a complete memoization function
2. Create a counter module with advanced features
3. Write a function that demonstrates closure in an event-driven scenario

Would you like me to elaborate on any of these examples or provide more in-depth explanations of any specific scenario?

You might also like