29. Modules, Closures, OOP, and Functional Programming Patterns
Why Advanced JS Patterns Matter
Modern JavaScript apps benefit from clean architecture and reusable code. Understanding modules, closures, object-oriented programming (OOP), and functional programming allows you to structure code for scalability, maintainability, and performance.
Modules: Organizing Your Code
Modules let you split code into separate files, each with its own scope. Named and default exports allow selective importing of functionality, making your code modular and easier to maintain.
// mathUtils.js
export const add = (a, b) => a + b;
export const multiply = (a, b) => a * b;
export default function subtract(a, b) {
return a - b;
}
// main.js
import subtract, { add, multiply } from './mathUtils.js';
console.log(add(2,3));
console.log(multiply(4,5));
console.log(subtract(10,4));Closures: Private State and Encapsulation
A closure occurs when a function retains access to its outer scope even after the outer function has finished executing. Closures are useful for creating private variables and encapsulating logic.
function createCounter() {
let count = 0; // private
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3Object-Oriented Programming (OOP)
OOP allows you to model real-world entities as objects with properties and methods. ES6 classes simplify creating reusable objects with inheritance.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound.`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks.`);
}
}
const dog = new Dog('Rex');
dog.speak(); // Rex barks.Functional Programming Patterns
Functional programming emphasizes pure functions, immutability, and higher-order functions. It helps write predictable, testable, and composable code.
// Higher-order functions
const numbers = [1,2,3,4,5];
const doubled = numbers.map(n => n * 2);
const even = numbers.filter(n => n % 2 === 0);
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(doubled, even, sum);Combining Patterns
In real-world apps, these patterns often work together. For example, closures can be used inside modules to keep state private, while classes and functional utilities can manage complex behaviors.
// Module with closure
export function createTodoManager() {
const todos = [];
return {
add(todo) { todos.push(todo); },
list() { return [...todos]; }, // immutable copy
};
}Mini Challenge
1. Create a module that manages a list of products using closures for private storage. 2. Add methods to add, remove, and list products. 3. Implement a class for a User with methods to buy a product and view purchases. 4. Use higher-order functions to filter purchased products by category.