// Global scope — anywhere accessible
let globalVar = "I'm global";
function outer() {
// Function (local) scope
let outerVar = "I'm in outer";
function inner() {
// Nested function scope
let innerVar = "I'm in inner";
console.log(globalVar); // ✅ visible
console.log(outerVar); // ✅ visible (lexical scope)
console.log(innerVar); // ✅ visible
}
console.log(globalVar); // ✅
console.log(outerVar); // ✅
// console.log(innerVar); // ❌ ReferenceError
}
// Block scope — let/const
{
let blockVar = "block";
const BLOCK_CONST = 42;
var notBlock = "var leaks!"; // ⚠️ var ignores block scope!
}
// console.log(blockVar); // ❌ ReferenceError
// console.log(notBlock); // ✅ "var leaks!" — DON'T use var
// Lexical scope = function သည် ရေးထားသည့်နေရာ ရဲ့ scope ကို သိ
// Basic closure
function makeCounter() {
let count = 0; // ← outer variable
// Inner function — closes over "count"
return function() {
count++;
return count;
};
}
const counter1 = makeCounter();
const counter2 = makeCounter(); // separate closure!
counter1(); // 1
counter1(); // 2
counter1(); // 3
counter2(); // 1 ← own "count" — not shared!
counter2(); // 2
// count is PRIVATE — can't access from outside
// counter1.count → undefined
// 1. Private data (encapsulation without class)
function createWallet(initialBalance) {
let balance = initialBalance; // private!
return {
deposit(amount) { balance += amount; return balance; },
withdraw(amount) {
if (amount > balance) return "Insufficient";
balance -= amount;
return balance;
},
getBalance() { return balance; }
};
}
const wallet = createWallet(100);
wallet.deposit(50); // 150
wallet.withdraw(30); // 120
wallet.getBalance(); // 120
// wallet.balance → undefined (private!)
// 2. Function factory
function multiply(multiplier) {
return (num) => num * multiplier; // closes over multiplier
}
const double = multiply(2);
const triple = multiply(3);
const tenTimes = multiply(10);
double(5); // 10
triple(5); // 15
tenTimes(7); // 70
// 3. Memoization (cache results)
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key] !== undefined) {
return cache[key]; // cached!
}
cache[key] = fn(...args);
return cache[key];
};
}
function slowSquare(n) {
// imagine expensive calculation
return n * n;
}
const fastSquare = memoize(slowSquare);
fastSquare(10); // calculates: 100
fastSquare(10); // from cache: 100 (instant!)
fastSquare(20); // calculates: 400
// IIFE = define and call immediately
// Use: isolate scope, avoid polluting global
(function() {
const privateVar = "only here";
console.log("IIFE runs immediately!");
// privateVar — accessible here but not outside
})();
// Arrow function IIFE
(() => {
console.log("Arrow IIFE");
})();
// IIFE with return value
const result = (function() {
const x = 10;
const y = 20;
return x + y;
})(); // result = 30
// IIFE with parameters
(function(name) {
console.log(`Hello, ${name}!`);
})("Ko Ko");
// Module pattern (pre-ES6 modules)
const Counter = (function() {
let count = 0; // private
return {
increment() { count++; },
decrement() { count--; },
getCount() { return count; }
};
})();
Counter.increment();
Counter.increment();
Counter.getCount(); // 2
// Partial application = pre-fill some arguments
function add(a, b, c) {
return a + b + c;
}
function partial(fn, ...presetArgs) {
return function(...laterArgs) {
return fn(...presetArgs, ...laterArgs);
};
}
const add5 = partial(add, 5); // a=5 preset
const add5and10 = partial(add, 5, 10); // a=5, b=10 preset
add5(3, 2); // 5+3+2 = 10
add5and10(7); // 5+10+7 = 22
// Currying = transform f(a,b,c) → f(a)(b)(c)
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn(...args);
}
return function(...more) {
return curried(...args, ...more);
};
};
}
const curriedAdd = curry((a, b, c) => a + b + c);
curriedAdd(1)(2)(3); // 6
curriedAdd(1, 2)(3); // 6
curriedAdd(1)(2, 3); // 6
curriedAdd(1, 2, 3); // 6
← JS 11 | Next: JS 13 → Design Patterns →