Sometimes in JavaScript, you want to give a function or class extra powers, like:
- Logging every time it’s called
- Automatically validating parameters
- Caching heavy computations
But adding all this code inside every function… 😵💫 Total code chaos!
That’s where Decorators come in: they let you add superpowers to functions or classes without touching their code.
🧩 1. What is a Decorator?
A decorator is a magic function that takes a function or class and enhances it.
- The original function or class remains unchanged
- Decorators add extra behavior
- They’re reusable and keep your code clean
Analogy:
- Function = a hero 🦸
- Decorator = the hero’s magical cape ✨
- Result = a superpowered hero 💥
🔹 2. Simple Example: Logging Decorator
Scenario: Log whenever a function is called
Regular JS:
function greet(name) {
console.log(`Hello ${name}!`);
console.log("greet function was called!");
}
greet("Alice");
⚠️ Problem: If you have 50 functions, you need to add this everywhere 😵
Repetitive and hard to maintain.
With Decorator:
function log(target, key, descriptor) {
const original = descriptor.value; // Original function
descriptor.value = function(...args) {
console.log(`${key} called with arguments: ${args}`);
return original.apply(this, args); // Call the original function
};
return descriptor;
}
class Greeter {
@log
greet(name) {
console.log(`Hello ${name}!`);
}
}
const g = new Greeter();
g.greet("Alice");
✅ Output:
greet called with arguments: Alice
Hello Alice!
📌 Explanation:
@log→ gives the function a superpower ✨target→ the class or object the function belongs tokey→ method namedescriptor.value→ original functionapply(this, args)→ calls the original function with its arguments
💡 Pro tip: Logging decorators are lifesavers during debugging.
🧠 3. Validation Decorator
Sometimes functions need safety checks: prevent missing or invalid parameters.
function validate(target, key, descriptor) {
const original = descriptor.value;
descriptor.value = function(name) {
if (!name) {
throw new Error("Name is required!");
}
return original.apply(this, [name]);
};
return descriptor;
}
class UserGreeter {
@validate
greet(name) {
console.log(`Hi ${name}!`);
}
}
const u = new UserGreeter();
u.greet(""); // ❌ Error: Name is required!
u.greet("Alice"); // ✅ Hi Alice!
📌 Fun analogy:
This decorator = a bouncer at the door 🚪
No name? “You shall not pass!”
💡 Tip:
Validation decorators are perfect for forms and user input
Eliminates repetitive code
🧩 4. Caching Decorator
Some functions are heavy computations.
Decorators can store results, making repeated calls super fast ⚡
function cache(target, key, descriptor) {
const original = descriptor.value;
const memory = {};
descriptor.value = function(num) {
if(memory[num] !== undefined) {
console.log(`Fetched from cache: ${num}`);
return memory[num];
}
const result = original.apply(this, [num]);
memory[num] = result;
return result;
};
return descriptor;
}
class Calculator {
@cache
factorial(n) {
console.log(`Calculating: ${n}!`);
return n <= 1 ? 1 : n * this.factorial(n - 1);
}
}
const c = new Calculator();
console.log(c.factorial(5)); // Calculating...
console.log(c.factorial(5)); // Fetched from cache!
📌 Explanation:
memory→ cache object- If the result was calculated before, it returns the cached value
apply→ runs the original function
💡 Pro tip:
- Great for CPU-intensive functions
- Use caching decorators for API calls or heavy computations
🧠 5. Combining Decorators
A function can have logging, validation, and caching decorators applied together.
Order matters: validation → caching → logging usually makes sense.
class SuperGreeter {
@log
@cache
@validate
greet(name) {
console.log(`Hi ${name}!`);
}
}
⚡ Note: Decorators are applied top-down, so order affects behavior.
🎉 6. Usage Rules and Tips
- Should be reusable
- Should not modify the original function or class
- Keep complex code clean and readable
- Combine multiple decorators for extra superpowers
💡 Bonus Tip:
Logging + Validation + Caching = “Superpowered Function”
Modern, clean, and maintainable approach in new JS projects
🎯 7. Conclusion: Decorators Make You a JS Superhero
- Code becomes shorter, cleaner, and readable
- Add extra features to functions and classes effortlessly
- Automate repetitive tasks like logging, validation, caching
- Feel like a JavaScript superhero 🦸♂️✨
