Decorators are a simple way to wrap code and a design pattern that extends the functionality of wrapped code without modifying it.
Although decorators are widely used in languages such as TypeScript and Python, support for JavaScript decorators is still a stage 2 proposal. However, we can use JavaScript decorators with the Babel and TypeScript compilers.
In JavaScript, decorators have a special syntax. They are prefixed with the @
symbol before the code we need to decorate. Additionally, you can use more than one decorator at a time.
@readonly
class Example {
@log()
exampleFunction() {}
}
The concept of decorators is not new to JavaScript, because higher-order functions are another form of function decorators.
In general, we can distinguish three types of decorators in JavaScript:
Function decorator : Wraps functions around functions.
Class decorator : applies to the entire class at once.
Class member decorator : applies to members of a class
Currently, you cannot run class decorators in a browser or node.js environment because they require translator support. However, if you use functional decorators, you can run them anywhere.
Function decoratorโ
We can try wrapping one function around another to extend functionality without changing the original function.
function logDecorator(fn) {
return function () {
console.log(`call ${fn.name} and params ${[...arguments]}`);
fn.apply(this, arguments);
};
}
function add(a, b) {
return a + b;
}
const wrapped = logDecorator(add);
console.log(wrapped(1, 2));
Class decoratorโ
A Class Decorator is declared just before a class declaration. The class decorator is applied to the constructor of the class and can be used to observe, modify, or replace a class definition.
function logDecorator(target) {
return function (...args) {
console.log(`Target is ${target} and args are ${args}`);
return new Target(...args);
};
}
@logDecorator
class Operator {
constructor(a, b) {
this.a = a;
this.b = b;
}
}
const op = new Operator(1, 2);
tip
You can run code in jsfiddle.net, select the babel + jax in the editor.

Class method decoratorโ
Class method decorators are a little different. Let's declare a decorator:
function log(target, name, descriptor) {
const original = descriptor.value;
descriptor.value = function () {
console.log(`call ${name} and params is ${[...arguments]}`);
return original.apply(this, arguments);
};
return descriptor;
}
Now you can use it to decorate a class methods with @
+ decoratorName:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
@log
getInfo() {
console.log(`${this.name} is a ${this.age} years old`);
}
}
const p = new Person("jstyro", 18);
p.getInfo();