# JavaScript Advanced Guide ## Table of Contents - [Introduction](#introduction) - [Object-Oriented Programming (OOP)](#object-oriented-programming-oop) - [Classes](#classes) - [Inheritance](#inheritance) - [Private Fields](#private-fields) - [Static Methods and Properties](#static-methods-and-properties) - [Getters and Setters](#getters-and-setters) - [Prototype System](#prototype-system) - [Prototype Chain](#prototype-chain) - [Prototypal Inheritance](#prototypal-inheritance) - [Object.create](#objectcreate) - [Closures and Scope](#closures-and-scope) - [Understanding Closures](#understanding-closures) - [Practical Closure Examples](#practical-closure-examples) - [Memory Considerations](#memory-considerations) - [The this Keyword Deep Dive](#the-this-keyword-deep-dive) - [Binding this](#binding-this) - [call, apply, and bind](#call-apply-and-bind) - [Asynchronous Patterns](#asynchronous-patterns) - [Event Loop](#event-loop) - [Callback Queue](#callback-queue) - [Microtasks vs Macrotasks](#microtasks-vs-macrotasks) - [Advanced Promise Patterns](#advanced-promise-patterns) - [Design Patterns](#design-patterns) - [Module Pattern](#module-pattern) - [Singleton](#singleton) - [Factory](#factory) - [Observer](#observer) - [Middleware](#middleware) - [Performance Optimization](#performance-optimization) - [Debouncing and Throttling](#debouncing-and-throttling) - [Memoization](#memoization) - [Lazy Loading](#lazy-loading) - [Memory Management](#memory-management) - [Garbage Collection](#garbage-collection) - [Memory Leaks](#memory-leaks) - [Advanced Array Operations](#advanced-array-operations) - [Typed Arrays](#typed-arrays) - [Array Buffers](#array-buffers) - [Symbol and Iteration](#symbol-and-iteration) - [Symbol](#symbol) - [Iterators and Generators](#iterators-and-generators) - [Reflect API](#reflect-api) - [Proxy API](#proxy-api) --- ## Introduction This guide covers advanced JavaScript concepts including object-oriented programming, the prototype system, closures, the event loop, design patterns, and performance optimization. These concepts will help you write more sophisticated and efficient code. --- ## Object-Oriented Programming (OOP) ### Classes Classes in JavaScript provide a cleaner syntax for creating objects and implementing inheritance: ```javascript // Class declaration class Person { // Constructor - called when creating new instance constructor(name, age) { this.name = name; this.age = age; } // Method greet() { return `Hello, my name is ${this.name}`; } // Another method celebrateBirthday() { this.age++; return `Happy birthday! Now I am ${this.age}`; } } // Creating an instance const alice = new Person("Alice", 25); console.log(alice.greet()); // "Hello, my name is Alice" console.log(alice.celebrateBirthday()); // "Happy birthday! Now I am 26" // Class expression const Animal = class { constructor(species) { this.species = species; } speak() { return `${this.species} makes a sound`; } }; ``` ### Inheritance Use `extends` to create a class that inherits from another: ```javascript // Parent class class Animal { constructor(name) { this.name = name; } speak() { return `${this.name} makes a sound`; } move() { return `${this.name} moves`; } } // Child class class Dog extends Animal { constructor(name, breed) { super(name); // Call parent constructor this.breed = breed; } // Override parent method speak() { return `${this.name} barks`; } // New method specific to Dog fetch() { return `${this.name} fetches the ball`; } } const dog = new Dog("Buddy", "Golden Retriever"); console.log(dog.speak()); // "Buddy barks" console.log(dog.move()); // "Buddy moves" (inherited) console.log(dog.fetch()); // "Buddy fetches the ball" console.log(dog instanceof Dog); // true console.log(dog instanceof Animal); // true ``` ### Private Fields Private fields (prefixed with `#`) encapsulate data: ```javascript class BankAccount { // Private fields #balance; #transactions = []; constructor(initialBalance = 0) { this.#balance = initialBalance; } // Public method to get balance getBalance() { return this.#balance; } // Deposit money deposit(amount) { if (amount <= 0) { throw new Error("Deposit amount must be positive"); } this.#balance += amount; this.#transactions.push({ type: 'deposit', amount }); return this.#balance; } // Withdraw money withdraw(amount) { if (amount <= 0) { throw new Error("Withdrawal amount must be positive"); } if (amount > this.#balance) { throw new Error("Insufficient funds"); } this.#balance -= amount; this.#transactions.push({ type: 'withdraw', amount }); return this.#balance; } // Private method #logTransaction(type, amount) { console.log(`${type}: $${amount}`); } } const account = new BankAccount(1000); console.log(account.getBalance()); // 1000 account.deposit(500); // 1500 // console.log(account.#balance); // SyntaxError - can't access private field // console.log(account.#transactions); // SyntaxError ``` ### Static Methods and Properties Static members belong to the class itself, not instances: ```javascript class MathUtils { static PI = 3.14159; static add(a, b) { return a + b; } static factorial(n) { if (n <= 1) return 1; return n * this.factorial(n - 1); } // Static factory method static fromDegrees(degrees) { return degrees * (MathUtils.PI / 180); } } console.log(MathUtils.PI); // 3.14159 console.log(MathUtils.add(2, 3)); // 5 console.log(MathUtils.factorial(5)); // 120 console.log(MathUtils.fromDegrees(90)); // ~1.57 // Cannot call static on instance const utils = new MathUtils(); // utils.add(2, 3); // TypeError ``` ### Getters and Setters Getters and setters provide controlled access to properties: ```javascript class Temperature { constructor(celsius) { this.celsius = celsius; } // Getter get fahrenheit() { return (this.celsius * 9/5) + 32; } // Setter set fahrenheit(value) { this.celsius = (value - 32) * 5/9; } get kelvin() { return this.celsius + 273.15; } set kelvin(value) { this.celsius = value - 273.15; } } const temp = new Temperature(25); console.log(temp.celsius); // 25 console.log(temp.fahrenheit); // 77 console.log(temp.kelvin); // 298.15 temp.fahrenheit = 100; console.log(temp.celsius); // ~37.78 ``` --- ## Prototype System Every JavaScript object has a prototype, which is another object from which it inherits properties. ### Prototype Chain ```javascript // Every object has a prototype const obj = {}; console.log(obj.__proto__); // Object.prototype console.log(obj.__proto__.__proto__); // null // Arrays inherit from Array.prototype const arr = [1, 2, 3]; console.log(arr.__proto__ === Array.prototype); // true console.log(arr.__proto__.__proto__ === Object.prototype); // true // Functions inherit from Function.prototype function foo() {} console.log(foo.__proto__ === Function.prototype); // true ``` ### Prototypal Inheritance ```javascript // Create object with specific prototype const animal = { speak() { return `${this.name} makes a sound`; }, move() { return `${this.name} moves`; } }; const dog = Object.create(animal); dog.name = "Buddy"; dog.breed = "Golden Retriever"; console.log(dog.speak()); // "Buddy makes a sound" console.log(dog.move()); // "Buddy moves" console.log(dog.hasOwnProperty('name')); // true console.log(dog.hasOwnProperty('speak')); // false (inherited) console.log(animal.isPrototypeOf(dog)); // true ``` ### Object.create ```javascript // Creating inheritance chain const Mammal = { isWarmBlooded: true, giveBirth() { return `${this.name} gives live birth`; } }; const Primate = Object.create(Mammal); Primate.hasOpposableThumbs = true; Primate.useTools = function() { return `${this.name} uses tools`; }; const Human = Object.create(Primate); Human.name = "Alice"; Human.speak = function() { return `${this.name} speaks`; }; console.log(Human.isWarmBlooded); // true (inherited from Mammal) console.log(Human.hasOpposableThumbs); // true (inherited from Primate) console.log(Human.useTools()); // "Alice uses tools" console.log(Human.speak()); // "Alice speaks" console.log(Human.giveBirth()); // "Alice gives live birth" ``` --- ## Closures and Scope ### Understanding Closures A closure is a function that remembers its outer variables even after the outer function has returned: ```javascript // Simple closure example function createCounter() { let count = 0; return function() { count++; return count; }; } const counter = createCounter(); console.log(counter()); // 1 console.log(counter()); // 2 console.log(counter()); // 3 // Each call creates a new closure const counter2 = createCounter(); console.log(counter2()); // 1 (separate count) // Closure with parameters function createMultiplier(factor) { return function(number) { return number * factor; }; } const double = createMultiplier(2); const triple = createMultiplier(3); console.log(double(5)); // 10 console.log(triple(5)); // 15 ``` ### Practical Closure Examples ```javascript // Private variables via closure function createBankAccount(initialBalance) { let balance = initialBalance; return { deposit(amount) { if (amount > 0) { balance += amount; return balance; } throw new Error("Invalid amount"); }, withdraw(amount) { if (amount > 0 && amount <= balance) { balance -= amount; return balance; } throw new Error("Invalid amount or insufficient funds"); }, getBalance() { return balance; } }; } const account = createBankAccount(100); console.log(account.getBalance()); // 100 account.deposit(50); console.log(account.getBalance()); // 150 account.withdraw(75); console.log(account.getBalance()); // 75 // Event handler with closure function setupButtonHandler(buttonId, count) { const button = document.getElementById(buttonId); let clickCount = count || 0; button.addEventListener('click', function() { clickCount++; console.log(`Button clicked ${clickCount} times`); }); } // Function factory function createGame(name) { let score = 0; return { name, increaseScore(points) { score += points; console.log(`${name}: ${score}`); }, reset() { score = 0; } }; } const game1 = createGame("Game 1"); const game2 = createGame("Game 2"); game1.increaseScore(10); // "Game 1: 10" game2.increaseScore(20); // "Game 2: 20" ``` ### Memory Considerations ```javascript // Potential memory leak - closure holding reference function leakMemory() { const largeData = new Array(1000000).fill("data"); return function() { return largeData[0]; // Keeps largeData in memory }; } // Better approach - avoid holding unnecessary references function noLeakMemory() { const largeData = new Array(1000000).fill("data"); return function() { return largeData[0]; // Necessary reference }; // largeData becomes eligible for GC after function returns } ``` --- ## The this Keyword Deep Dive ### Binding this ```javascript // In methods, 'this' refers to the object const person = { name: "Alice", greet() { return `Hello, I'm ${this.name}`; } }; console.log(person.greet()); // "Hello, I'm Alice" // When extracted, 'this' loses context const greetFn = person.greet; console.log(greetFn()); // "Hello, I'm undefined" (or error in strict mode) // Solution 1: Bind const boundGreet = person.greet.bind(person); console.log(boundGreet()); // "Hello, I'm Alice" // Solution 2: Arrow function in object const person2 = { name: "Bob", greet: () => { return `Hello, I'm ${this.name}`; // 'this' is lexically bound } }; ``` ### call, apply, and bind ```javascript function greet(greeting, punctuation) { return `${greeting}, ${this.name}${punctuation}`; } const person = { name: "Alice" }; // call - invoke with specific 'this' and arguments console.log(greet.call(person, "Hello", "!")); // "Hello, Alice!" // apply - invoke with specific 'this' and array of arguments console.log(greet.apply(person, ["Hi", "."])); // "Hi, Alice." // bind - create new function with bound 'this' const boundGreet = greet.bind(person); console.log(boundGreet("Howdy", "?")); // "Howdy, Alice?" // Partial application with bind const greetAlice = greet.bind(person, "Hello"); console.log(greetAlice("!")); // "Hello, Alice!" ``` --- ## Asynchronous Patterns ### Event Loop ```javascript // JavaScript is single-threaded but handles async via event loop console.log("1. Start"); setTimeout(() => { console.log("2. Timeout callback"); }, 0); Promise.resolve().then(() => { console.log("3. Promise resolved"); }); console.log("4. End"); // Output order: // 1. Start // 4. End // 3. Promise resolved (microtask) // 2. Timeout callback (macrotask) ``` ### Callback Queue ```javascript // Microtasks (Promises, queueMicrotask) Promise.resolve().then(() => console.log("Promise 1")); queueMicrotask(() => console.log("Microtask")); // Macrotasks (setTimeout, setInterval, I/O) setTimeout(() => console.log("Timeout"), 0); // Execution order console.log("Start"); setTimeout(() => console.log("Timeout"), 0); Promise.resolve().then(() => console.log("Promise 1")) .then(() => Promise.resolve().then(() => console.log("Promise 2"))); queueMicrotask(() => console.log("Microtask")); console.log("End"); // Output: // Start // End // Promise 1 // Promise 2 // Microtask // Timeout ``` ### Advanced Promise Patterns ```javascript // Promise timeout function withTimeout(promise, ms) { const timeout = new Promise((_, reject) => { setTimeout(() => reject(new Error("Timeout")), ms); }); return Promise.race([promise, timeout]); } // Retry with exponential backoff async function retry(fn, maxAttempts = 3, delay = 1000) { for (let attempt = 1; attempt <= maxAttempts; attempt++) { try { return await fn(); } catch (error) { if (attempt === maxAttempts) throw error; await new Promise(r => setTimeout(r, delay * attempt)); } } } // Promise queue - run promises sequentially async function runSequentially(promises) { const results = []; for (const promise of promises) { results.push(await promise); } return results; } // Promise cache const promiseCache = new Map(); async function fetchWithCache(url) { if (promiseCache.has(url)) { return promiseCache.get(url); } const promise = fetch(url).then(r => r.json()); promiseCache.set(url, promise); return promise; } ``` --- ## Design Patterns ### Module Pattern ```javascript // Using IIFE to create private scope const CounterModule = (function() { // Private state let count = 0; // Private function function validate(value) { return typeof value === 'number' && !isNaN(value); } // Public API return { increment(value = 1) { if (validate(value)) { count += value; return count; } return count; }, decrement(value = 1) { if (validate(value)) { count -= value; return count; } return count; }, getCount() { return count; }, reset() { count = 0; return count; } }; })(); console.log(CounterModule.increment()); // 1 console.log(CounterModule.increment(5)); // 6 console.log(CounterModule.getCount()); // 6 console.log(CounterModule.count); // undefined (private) ``` ### Singleton ```javascript // Singleton using class class Singleton { static #instance = null; constructor() { if (Singleton.#instance) { return Singleton.#instance; } Singleton.#instance = this; this.data = {}; } set(key, value) { this.data[key] = value; } get(key) { return this.data[key]; } } const a = new Singleton(); const b = new Singleton(); console.log(a === b); // true // Singleton using IIFE const Database = (function() { let instance = null; function createInstance() { return { query(sql) { console.log(`Executing: ${sql}`); } }; } return { getInstance() { if (!instance) { instance = createInstance(); } return instance; } }; })(); const db1 = Database.getInstance(); const db2 = Database.getInstance(); console.log(db1 === db2); // true ``` ### Factory ```javascript // Factory function function createUser(type, data) { const baseUser = { created: new Date(), greet() { return `Hello, I'm ${this.name}`; } }; switch (type) { case 'admin': return { ...baseUser, ...data, permissions: ['read', 'write', 'delete'] }; case 'moderator': return { ...baseUser, ...data, permissions: ['read', 'write'] }; case 'user': return { ...baseUser, ...data, permissions: ['read'] }; default: throw new Error(`Unknown user type: ${type}`); } } const admin = createUser('admin', { name: 'Alice', email: 'alice@example.com' }); console.log(admin.permissions); // ['read', 'write', 'delete'] // Factory using classes class UserFactory { static create(type, data) { const baseProps = { id: Date.now(), createdAt: new Date(), type }; const typeSpecific = this.getTypeSpecificProps(type); return { ...baseProps, ...typeSpecific, ...data }; } static getTypeSpecificProps(type) { const types = { premium: { isPremium: true, maxStorage: '100GB' }, free: { isPremium: false, maxStorage: '5GB' } }; return types[type] || {}; } } ``` ### Observer ```javascript // Simple Event Emitter class EventEmitter { constructor() { this.events = {}; } on(event, callback) { if (!this.events[event]) { this.events[event] = []; } this.events[event].push(callback); } off(event, callback) { if (this.events[event]) { this.events[event] = this.events[event].filter(cb => cb !== callback); } } emit(event, ...args) { if (this.events[event]) { this.events[event].forEach(callback => callback(...args)); } } once(event, callback) { const wrapper = (...args) => { callback(...args); this.off(event, wrapper); }; this.on(event, wrapper); } } // Usage const emitter = new EventEmitter(); emitter.on('message', (data) => { console.log('Listener 1:', data); }); emitter.on('message', (data) => { console.log('Listener 2:', data.toUpperCase()); }); emitter.emit('message', 'Hello World'); // Listener 1: Hello World // Listener 2: HELLO WORLD ``` ### Middleware ```javascript // Middleware pattern for request processing class MiddlewareChain { constructor() { this.middlewares = []; } use(fn) { this.middlewares.push(fn); } async execute(context) { let index = 0; const next = async () => { if (index >= this.middlewares.length) { return context; } const middleware = this.middlewares[index++]; await middleware(context, next); }; await next(); return context; } } // Example middlewares const logging = async (ctx, next) => { console.log(`[${new Date().toISOString()}] ${ctx.method} ${ctx.url}`); await next(); console.log('Response status:', ctx.status); }; const auth = async (ctx, next) => { if (!ctx.user) { ctx.status = 401; return; } await next(); }; const validate = async (ctx, next) => { if (!ctx.body || Object.keys(ctx.body).length === 0) { ctx.status = 400; ctx.error = 'Request body required'; return; } await next(); }; // Usage const chain = new MiddlewareChain(); chain.use(logging); chain.use(auth); chain.use(validate); await chain.execute({ method: 'POST', url: '/api/users', user: { id: 1 }, body: { name: 'Alice' } }); ``` --- ## Performance Optimization ### Debouncing and Throttling ```javascript // Debounce - wait for function to stop being called function debounce(fn, delay) { let timeoutId; return function(...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => fn.apply(this, args), delay); }; } // Example - search input const handleSearch = debounce((query) => { console.log('Searching for:', query); }, 300); // User types "hello" // After 300ms of not typing, logs "Searching for: hello" // Throttle - limit function execution rate function throttle(fn, limit) { let inThrottle; return function(...args) { if (!inThrottle) { fn.apply(this, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; } // Example - scroll handler const handleScroll = throttle(() => { console.log('Scroll position:', window.scrollY); }, 100); window.addEventListener('scroll', handleScroll); ``` ### Memoization ```javascript // Simple memoization function memoize(fn) { const cache = new Map(); return function(...args) { const key = JSON.stringify(args); if (cache.has(key)) { return cache.get(key); } const result = fn.apply(this, args); cache.set(key, result); return result; }; } // Example - expensive calculation const fibonacci = memoize(function(n) { if (n <= 1) return n; return fibonacci(n - 1) + fibonacci(n - 2); }); console.log(fibonacci(40)); // Fast due to memoization console.log(fibonacci(40)); // Even faster from cache ``` ### Lazy Loading ```javascript // Lazy load images function lazyLoadImages() { const images = document.querySelectorAll('img[data-src]'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; img.removeAttribute('data-src'); observer.unobserve(img); } }); }); images.forEach(img => observer.observe(img)); } // Dynamic import async function loadFeature() { if (needsPremiumFeature()) { const { premiumFeature } = await import('./premium.js'); premiumFeature(); } } ``` --- ## Memory Management ### Garbage Collection JavaScript automatically cleans up unused memory through garbage collection: ```javascript // Objects become eligible for GC when no references exist let obj = { name: "Alice" }; obj = null; // Previous object is now eligible for GC // Closure can prevent GC function createLeak() { const largeData = new Array(10000000); return function() { return largeData.length; }; } const leak = createLeak(); // largeData stays in memory leak = null; // Now eligible for GC ``` ### Memory Leaks ```javascript // Common memory leak - forgotten timers let data = []; const interval = setInterval(() => { data.push(new Array(1000000)); }, 1000); // Clear to prevent leak clearInterval(interval); // Common leak - detached DOM nodes const container = document.getElementById('container'); const button = document.createElement('button'); container.appendChild(button); container.removeChild(button); // button still in memory if referenced // Common leak - global event listeners class Handler { constructor() { this.data = new Array(1000000); } handleClick() { console.log('Clicked'); } } const handler = new Handler(); document.addEventListener('click', handler.handleClick); // Remove to prevent leak document.removeEventListener('click', handler.handleClick); ``` --- ## Advanced Array Operations ### Typed Arrays ```javascript // Int8Array - signed 8-bit integers const int8 = new Int8Array([1, 2, 127, -128]); console.log(int8[0]); // 1 console.log(int8[3]); // -128 // Uint8Array - unsigned 8-bit integers const uint8 = new Uint8Array([255, 256]); // 256 becomes 0 console.log(uint8[0]); // 255 console.log(uint8[1]); // 0 // Float32Array - 32-bit floating point const float32 = new Float32Array([1.5, 2.5]); console.log(float32[0]); // 1.5 // Int16Array, Int32Array, Uint16Array, Uint32Array, etc. const int16 = new Int16Array(100); // Create array of 100 16-bit integers // Typed arrays have fixed length const arr = new Int8Array(3); arr[0] = 100; arr[1] = 200; // arr[2] is 0 by default // arr[3] would be out of bounds ``` ### Array Buffers ```javascript // Create buffer const buffer = new ArrayBuffer(16); console.log(buffer.byteLength); // 16 // View the buffer const view = new DataView(buffer); // Write values view.setInt8(0, 127); view.setInt16(2, 1000, true); // little-endian view.setFloat64(4, 3.14159); // Read values console.log(view.getInt8(0)); // 127 console.log(view.getInt16(2, true)); // 1000 console.log(view.getFloat64(4)); // 3.14159 ``` --- ## Symbol and Iteration ### Symbol ```javascript // Create unique symbol const sym1 = Symbol('description'); const sym2 = Symbol('description'); console.log(sym1 === sym2); // false // Well-known symbols // Symbol.iterator - custom iteration // Symbol.toStringTag - custom toString // Symbol.hasInstance - custom instanceof // Custom iterator const collection = { items: [1, 2, 3], [Symbol.iterator]() { let index = 0; return { next: () => { if (index < this.items.length) { return { value: this.items[index++], done: false }; } return { done: true }; } }; } }; for (const item of collection) { console.log(item); // 1, 2, 3 } ``` ### Iterators and Generators ```javascript // Iterator protocol const stringIterator = "hello"[Symbol.iterator](); console.log(stringIterator.next()); // { value: 'h', done: false } console.log(stringIterator.next()); // { value: 'e', done: false } // Generator functions function* numberGenerator() { yield 1; yield 2; yield 3; } const gen = numberGenerator(); console.log(gen.next()); // { value: 1, done: false } console.log(gen.next()); // { value: 2, done: false } console.log(gen.next()); // { value: 3, done: false } console.log(gen.next()); // { value: undefined, done: true } // Generator with parameters function* fibonacci() { let a = 0, b = 1; while (true) { yield a; [a, b] = [b, a + b]; } } const fib = fibonacci(); console.log(fib.next().value); // 0 console.log(fib.next().value); // 1 console.log(fib.next().value); // 1 console.log(fib.next().value); // 2 console.log(fib.next().value); // 3 ``` --- ## Reflect API ```javascript // Reflect - built-in object for metaprogramming // Create object with prototype const proto = { greet() { return "Hello"; } }; const obj = Reflect.create(proto); console.log(obj.greet()); // "Hello" // Check if property exists console.log(Reflect.has({ a: 1 }, 'a')); // true console.log(Reflect.has({ a: 1 }, 'b')); // false // Get/set properties const target = { a: 1 }; Reflect.set(target, 'b', 2); console.log(Reflect.get(target, 'b')); // 2 // Delete property Reflect.deleteProperty({ a: 1 }, 'a'); console.log(Reflect.has({ a: 1 }, 'a')); // false // Apply function function add(a, b) { return a + b; } console.log(Reflect.apply(add, null, [2, 3])); // 5 ``` --- ## Proxy API ```javascript // Proxy - intercept and customize operations on objects const handler = { get(target, property) { console.log(`Getting ${property}`); return target[property]; }, set(target, property, value) { console.log(`Setting ${property} to ${value}`); target[property] = value; return true; } }; const proxy = new Proxy({}, handler); proxy.name = "Alice"; // Setting name to Alice console.log(proxy.name); // Getting name - Alice // Validation with Proxy const validator = { set(target, property, value) { if (property === 'age') { if (typeof value !== 'number' || value < 0 || value > 150) { throw new RangeError('Invalid age'); } } target[property] = value; return true; } }; const person = new Proxy({}, validator); person.age = 25; // OK // person.age = -5; // RangeError ``` --- ## Summary | Topic | Key Concepts | |-------|--------------| | **OOP** | Classes, inheritance, private fields, static methods | | **Prototypes** | Prototype chain, Object.create, prototypal inheritance | | **Closures** | Function scope, private variables, memory considerations | | **this** | Binding, call/apply/bind | | **Async** | Event loop, microtasks, macrotasks | | **Patterns** | Module, Singleton, Factory, Observer, Middleware | | **Performance** | Debouncing, throttling, memoization | | **Memory** | Garbage collection, memory leaks | | **Advanced Arrays** | Typed arrays, ArrayBuffer | | **Metaprogramming** | Symbol, Reflect, Proxy, Generators |