What are Decorators and How are they used in JavaScript?
Last Updated :
25 Oct, 2024
Decorators in JavaScript are a design pattern that enhances an object’s behavior by wrapping it with additional functionality, without altering its original code. It enable modifications like logging or security checks without changing the underlying implementation. It adopted from languages like Python and C#, allows for flexible extension of object functionality in JavaScript applications.

How to Use Decorators in JavaScript?
A decorator is a higher-order function that modifies the behavior of a function, method, or class. Decorators are used for extending the functionality of a function, method, or class without modifying its code.
Syntax
let variable = function(object) {
object.property = 'characteristic';
}
// Use as decorator
@variable
class GFG
{ }
console.log(GFG.property);
Example: It is an example of decorators in older JavaScript versions. The `add` function accepts `print` as a parameter, where `print` acts as a decorator appending “is best” to the string “GFG”. By using `add`, we extend and invoke `print`, effectively concatenating the strings.
JavaScript
// Working of Decorators in javascript
// "add" function takes the function as
// a parameter for wrapping function
// "print" is wrapped
function add(fn) {
return function (s) {
var gg = s + ' is Best';
// By concatenating we extend
// the function "add"
fn(gg);
}
}
// Decorated function
function print(s) {
console.log(s);
}
// Calling "add"
var g = add(print);
g('GFG');
Output
GFG is Best
Steps to Run Decorators in JavaScript
To run the decorators in JavaScript, we need to configure babel in out projec. Below is a step-by-step guide
Step 1: Initialize a Node App
npm init
Step 2: Install Babel and Required Plugins
npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/plugin-proposal-decorators
The updated dependencies after installing above pacakges are:
"devDependencies": {
"@babel/cli": "^7.25.7",
"@babel/core": "^7.25.8",
"@babel/plugin-proposal-decorators": "^7.25.7",
"@babel/preset-env": "^7.25.8"
}
Step 3: Configure .babelrc file
// Filename - .babelrc
{
"plugins": [
["@babel/plugin-proposal-decorators", { "version": "legacy" }]
],
"presets": ["@babel/preset-env"]
}
Step 4: Define Decorator in index.js file
// Filename - index.js
let variable = function (target) {
target.property = 'GFG is best';
}
// Decorator
@variable
class GFG { }
// Print in the console
console.log(GFG.property);
Step 5: Compile the code using Babel
npx babel index.js --out-file compiled_output.js
This command will output the compiled file which will look like this:
JavaScript
// Filename - compiled_output.js
"use strict";
function _typeof(o) {
"@babel/helpers - typeof";
return (_typeof = "function" == typeof Symbol &&
"symbol" == typeof Symbol.iterator
? function (o) { return typeof o; }
: function (o) {
return o &&
"function" == typeof Symbol &&
o.constructor === Symbol &&
o !== Symbol.prototype
? "symbol"
: typeof o;
}), _typeof(o);
}
var _class;
function _defineProperties(e, r) {
for (var t = 0; t < r.length; t++) {
var o = r[t];
(o.enumerable = o.enumerable || !1),
(o.configurable = !0), "value" in o &&
(o.writable = !0), Object.defineProperty(
e, _toPropertyKey(o.key), o);
}
}
function _createClass(e, r, t) {
return r && _defineProperties(e.prototype, r), t &&
_defineProperties(e, t), Object.defineProperty(e, "prototype", {
writable: !1
}), e;
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == _typeof(i) ? i : i + "";
}
function _toPrimitive(t, r) {
if ("object" != _typeof(t) || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != _typeof(i)) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function _classCallCheck(a, n) {
if (!(a instanceof n))
throw new TypeError("Cannot call a class as a function");
}
// Filename - index.js
var variable = function variable(target) {
target.property = "GFG is best";
};
// Decorator
var GFG = variable(
(_class = /*#__PURE__*/ _createClass(function GFG() {
_classCallCheck(this, GFG);
}))
) || _class; // Print in the console
console.log(GFG.property);
Step 6: Run the output file
node compiled_output.js
The below example illustrates the decorators in JavaScript:
Example 1: Defining a decorator variable that adds a property to the class GFG, which is then accessed to log “GFG is best” in the console.
JavaScript
let variable = function (target) {
target.property = 'GFG is best';
}
// Decorator
@variable
class GFG { }
// Print in the console
console.log(GFG.property);
Output
GFG is best
Example 2: Defining a decorator factory variable that sets a class property based on the passed argument, assigning “GFG is Green” to GFG.property and logging it.
JavaScript
let variable = function (color) {
return function (target) {
target.property = color;
}
};
// The value is passed in the decorator
@variable('GFG is Green')
class GFG { }
console.log(GFG.property);
Output
GFG is Green
Why to uses Decorator ?
- Decorators allow for decorating code in an efficient and understandable way.
- Applying the same techniques to different parts of the code or wrapping functions manually can be challenging.
- In ES6, decorators help resolve these difficulties by providing a clear syntax for wrapping code with functions or additional logic.
- Decorators offer a standardized approach to applying wrappers around functions or other code blocks.
- Although JavaScript decorators are not yet directly supported, future versions may include native support for them.
Types of Decorators
Decorators are called by the appropriate details of the item which will be decorated. Decorators are actually functions that return another function. There are two types of decorators are supported now:
- Class member decorators
- Class Decorators
Class Member Decorators
These decorators are applied to a single member of a class. This decorator has properties, methods, getters, and setters. This decorator accepts 3 parameters:
- target: The class to which the member belongs to.
- name: Name of the class member.
- descriptor: Description of the member which is the object that is passed to Object.defineProperty.
Example 1: This example defines a method decorator gfg that logs the parameters and result of the add method in the geek class.
JavaScript
// Decorator function
function gfg(target, name, descriptor) {
let fn = descriptor.value;
// Checks if "descriptor.value" is a function
if (typeof fn == 'function') {
descriptor.value = function(...args) {
console.log(`parameters: ${args}`);
let result = fn.apply(this, args);
// Print the addition of passed arguments
console.log(`addition: ${result}`);
return result;
}
}
return descriptor;
}
class geek {
@gfg
add(a, b) {
return a + b;
}
}
let e = new geek();
e.add(100, 200);
Output
parameters: 100, 200
addition: 300
Example 2: This example demonstrates a readonly decorator to make the getColor method of the car class non-writable, preventing it from being overridden.
JavaScript
let readonly = function(target, key, descriptor) {
descriptor.writable = false;
return descriptor;
}
class car {
constructor(color) {
this.color = color;
}
// Decorator
@readonly
getColor() {
return this.color;
}
}
const rCar = new car('car is Black');
// When descriptor.writable = false;
rCar.getColor = function() {
// When descriptor.writable = true;
return 'car is not Black'
}
console.log(rCar.getColor());
Output
car is Black
Class Decorators
These decorators are applied to the entire class. These functions are called with a single parameter which is to be decorated. This function is a constructor function. These decorators are not applied to each instance of the class, it only applies to the constructor function. These decorators are less useful than class member decorators. Because we can use a simple function to do everything which can be done by these decorators.
Example: This example demonstrates using a log
decorator to log the parameters passed to the gfg
class constructor.
JavaScript
function log() {
// Decorator function
return function decorator(Class) {
// "arrow" function
return (...args) => {
console.log(`Parameters: ${args}`);
return new Class(...args);
};
};
}
// Decorators
@log
class gfg {
constructor(name, category) {
this.name = name;
this.category = category;
}
}
const e = new gfg('geek', 'code');
// Arguments for Demo: args
console.log(e);
Output
(...args) =>
{
console.log(`Parameters : args`);
return new Class(...args);
}
Benefits to use Decorators
- Decorators allow you to add new functionality to an object without modifying its code. This can be useful for adding behavior such as logging, error handling, or security checks, without changing the core functionality of the object.
- Decorators can make your code more modular and easier to maintain, as you can add or remove behavior independently of the core functionality of the object.
- Decorators can be easily composed, meaning that you can apply multiple decorators to the same object to achieve a desired behavior.
Drawbacks of using Decorators
- Decorators can make your code more complex, as they add an additional layer of abstraction to your code.
- Decorators can make your code harder to understand, especially if you are using multiple decorators on the same object.
- Decorators are a relatively new feature of JavaScript, and they are not supported in all environments.
- Overall, decorators are a useful tool that can help you add new behavior to your code in a flexible and modular way. However, it’s important to consider the potential complexity and readability trade-offs when using decorators in your code.
Similar Reads
What are decorators and how are they used in JavaScript ?
Decorators in JavaScript are a design pattern that enhances an object's behavior by wrapping it with additional functionality, without altering its original code. It enable modifications like logging or security checks without changing the underlying implementation. It adopted from languages like Py
8 min read
What are the class compositions in JavaScript ?
Class composition is a design pattern used to build complex classes by combining behaviours from multiple sources rather than relying solely on inheritance. Class composition enables combining multiple functionalities in a single object.It is a flexible alternative to inheritance, allowing for bette
3 min read
What are the classes and proxies in JavaScript ?
Classes: These are almost similar to functions, except they use a class keyword instead of a function keyword. Another important difference between functions and classes is that functions can be called in code before they are defined whereas classes must be defined before a class object is construct
4 min read
What to understand the Generator function in JavaScript ?
Generators generate value on the fly which means whenever there is a need for that value then only it will be generated. It means the value is generated but not stored in memory so it takes less time to execute. It uses asterick (*) symbol after the keyword function i.e. function* to tell javaScript
4 min read
What are decorators in Angular?
In Angular decorators are important for defining and configuring various application elements, providing an easy way to enhance the classes with additional functionality and provide metadata. In this article, we'll take a detailed look at the concept of Decorators in Angular. Table of Content What a
4 min read
What is a typical use case for anonymous functions in JavaScript ?
In this article, we will try to understand what exactly an Anonymous function is, and how we could declare it using the syntax provided in JavaScript further we will see some examples (use-cases) where we can use anonymous functions to get our results in the console. Before proceeding with the examp
4 min read
What are template engines in Express, and why are they used?
A Template Engine simplifies the use of static templates with minimal code. During runtime on the client side, variables in the template are replaced with actual values. These engines help developers create templates for web pages, written in a markup language with placeholders for dynamic content.
4 min read
How to create a JavaScript class in ES6 ?
A class describes the contents of objects belonging to it: it describes a set of data fields (called instance variables) and it defines the operations on those fields (called methods). In order words, it is also defined as the collection or a group of object that contains object data types along wit
2 min read
How are DOM utilized in JavaScript ?
What is DOM The document object Model (DOM) represents the full HTML document. When an HTML document is loaded within the browser, it becomes a document object. The root element represents the HTML document, its properties, and its methods. With the assistance of a document object, we will add dynam
3 min read
What are factory functions in JavaScript ?
In JavaScript, a factory function is a function that returns an object. It is a way of creating and returning objects in a more controlled and customizable manner. Factory functions are a form of design pattern that enables the creation of objects with specific properties and behaviors. Why it is us
2 min read