Understanding and Using Decorators in JavaScript (Frontend Development)
This article introduces JavaScript decorators, explains their relation to the decorator design pattern, shows how to configure Babel for decorator support, demonstrates class and method decorator syntax with detailed code examples, and discusses practical usage scenarios and execution order in modern front‑end projects.
Preface
In front‑end development you may have encountered syntax like @methodName and wondered what it does. The answer is the Decorator (or Decorator ) pattern, which allows dynamic addition of behavior to classes without modifying the original class definition.
What Is a Decorator
Decorator Pattern
The decorator pattern lets you add responsibilities to an object at runtime while keeping the object itself unchanged, similar to putting on different clothes for different weather.
In JavaScript, a Decorator is a syntactic sugar for this pattern, currently at Stage 2 of the TC39 proposal and requires Babel compilation.
How to Use Decorators
Third‑Party Library Usage
Babel ≥ 7.x
Install: npm install --save-dev @babel/plugin-proposal-decorators
Configure .babelrc : { "plugins": [ ["@babel/plugin-proposal-decorators", { "legacy": true }] ] }
Babel ≤ 6.x
Install: npm install --save-dev babel-plugin-transform-decorators-legacy
Configure .babelrc : { "plugins": ["transform-decorators-legacy"] }
Usage Syntax
A decorator is written as @ + expression returning a decorator function . Example:
@classDecorator
class TargetClass {
// class
@fieldDecorator
targetField = 0; // instance property
@funDecorator
targetFun() {}
@accessorDecorator
get targetGetFun() {}
}When multiple decorators are applied, they are executed from the outermost to the innermost (enter) and then from innermost to outermost (exit).
Scope of Decorators
Classes
Class instance properties (public, private, static)
Class methods (public, private, static)
Class accessors (getters/setters)
Function Decoration Limitation
Functions cannot be directly decorated because of function hoisting. To modify a function you can use higher‑order functions instead.
Decorator Principles
Class Decorators
Passing Arguments
function decorator(...args) {
args.forEach((arg, index) => {
console.log(`参数${index}`, arg);
});
}
@decorator
class TargetClass {}The decorator receives the class definition as its sole argument.
Return Value
function returnStr(targetClass) {
return 'hello world~';
}
function returnClass(targetClass) {
return targetClass;
}
@returnStr
class ClassA {}
@returnClass
class ClassB {}The decorator’s return value replaces the original class if it is truthy.
Practical Examples
Add a static attribute: function addAttribute(targetClass) { targetClass.isUseDecorator = true; } @addAttribute class TargetClass {} console.log(TargetClass.isUseDecorator); // true
Return a decorator factory to set custom content: function addAttribute(content) { return function decFn(targetClass) { targetClass.content = content; return targetClass; }; } @addAttribute('这是内容~~~') class TargetClass {} console.log(TargetClass.content); // 这是内容~~~
Add a prototype method: function decorator(targetClass) { targetClass.prototype.decFun = function () { console.log('这里是装饰器 decorator 添加的原型方法 decFun~'); }; } @decorator class TargetClass {} const instance = new TargetClass(); instance.decFun();
Method Decorators
Method decorators receive three arguments: the class prototype, the property name, and the property descriptor, similar to Object.defineProperty .
function readonly(target, name, descriptor) {
descriptor.writable = false;
return descriptor;
}
class Person {
@readonly
name = 'zhangsan';
}
const person = new Person();
console.log(person.name, Object.getOwnPropertyDescriptor(person, 'name'));Decorator Applications
Decorators can encapsulate repetitive logic such as data fetching in React components. By creating a getData decorator that wraps a component, you can centralize API calls and pass the fetched data via props.
// Decorator definition
function getData(params) {
return (Comp) => {
class WrapperComponent extends Component {
async getData() {
const data = await request('/xxx', { params });
this.setState({ data });
}
render() {
return
;
}
};
return WrapperComponent;
};
}
// Component usage
@getData({ id: '123' })
export default class Index extends Component {
render() {
const data = this.props.data;
return
我是组件一: {data}
;
}
}Conclusion
The article covered the concept, syntax, configuration, execution order, and practical use cases of JavaScript decorators, providing numerous code samples to help front‑end developers apply decorators effectively in their projects.
政采云技术
ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.