JavaScript Decorators are a robust feature that allows you to modify or enhance classes, methods, props, or parameters at design time. As of 2023, it’s not yet part of the official ECMAScript standard. However, decorators are widely used via transpilers which turn JS code into the browser readable JS code for you (like Babel). Currently, decorators are a stage 3 proposal, meaning that it is very likely this will become part of the official spec soon.
What Are JavaScript Decorators?
JavaScript Decorators are unique functions that can be applied to classes or members of classes in order to add other behavior to them without changing the original code. Decorators use an @decorator syntax and are called with the details of what they are decorating.
@log
class MyClass {
@readonly
method() {}
}
Why Use JavaScript Decorators?
- Cleaner code: They help separate cross-cutting concerns from business logic
- Reusability: Common functionality can be packaged as decorators and reused
- Declarative syntax: The
@
syntax makes it clear what enhancements are applied - Meta-programming: They enable powerful patterns for modifying program behavior

Types of JavaScript Decorators
1. Class Decorators
These decorate entire classes, allowing you to modify or replace the class definition.
function log(target) {
console.log(`Class ${target.name} was defined`);
return target;
}
@log
class MyClass {}
2. Method Decorators
Method decorators wrap class methods, enabling functionality like logging, memoization, or access control.
function log(target, name, descriptor) {
const original = descriptor.value;
descriptor.value = function(...args) {
console.log(`Calling ${name} with`, args);
const result = original.apply(this, args);
console.log(`Result:`, result);
return result;
};
return descriptor;
}
class Calculator {
@log
add(a, b) {
return a + b;
}
}
3. Property Decorators
These decorate class properties, useful for things like type checking or reactive programming.
function readonly(target, name, descriptor) {
descriptor.writable = false;
return descriptor;
}
class User {
@readonly
id = generateId();
}
4. Parameter Decorators
Parameter decorators are applied to function parameters, often used with dependency injection.
function validate(type) {
return function(target, key, index) {
// Store validation metadata
};
}
class API {
getUser(@validate('number') id) {
// ...
}
}
Common JavaScript Decorators Patterns
1. Logging Decorator
function log(target, name, descriptor) {
const original = descriptor.value;
descriptor.value = function(...args) {
console.log(`[${new Date().toISOString()}] ${name} called with:`, args);
return original.apply(this, args);
};
return descriptor;
}
2. Memoization Decorator
function memoize(target, name, descriptor) {
const original = descriptor.value;
const cache = new Map();
descriptor.value = function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = original.apply(this, args);
cache.set(key, result);
return result;
};
return descriptor;
}
3. Throttle/Debounce Decorator
function debounce(delay) {
return function(target, name, descriptor) {
const original = descriptor.value;
let timeout;
descriptor.value = function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => original.apply(this, args), delay);
};
return descriptor;
};
}
Using Decorators in Modern JavaScript
Since decorators aren’t yet natively supported in all environments, you’ll need transpilation.
Babel requires the @babel/plugin-proposal-decorators
plugin. The configuration differs based on which proposal version you target (legacy vs. modern).
TypeScript supports decorators via the experimentalDecorators
compiler option, though its implementation differs slightly from the current proposal.
Best Practices
- Keep decorators simple: They should do one thing well
- Document behavior: Decorators can make code behavior non-obvious
- Avoid side effects: Decorators should generally be pure functions
- Consider performance: Some decorators (like memoization) have memory implications
Conclusion
JavaScript Decorators offer an exceptionally flexible way to declaratively change and augment JavaScript classes and their members. Although the syntax may take some time to get used to, decorators will allow for clean, elegant solutions to common tasks like logging, caching, validation, and so on. With the proposal heading toward standardization, decorators are in the process of becoming a tool of significant focus and value in the JavaScript developer toolbox.
With correct usage, decorators will help keep your code DRY, more readable, and allow complex meta-programming patterns that would otherwise take more verbose approaches.