Master JavaScript Decorators: A Practical Guide to ES7 Enhancements

This article explains what JavaScript decorators are, how they work on classes and methods, how to configure Babel for ES7 support, and demonstrates real‑world uses such as mixins and simple AOP, providing clear code examples throughout.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Master JavaScript Decorators: A Practical Guide to ES7 Enhancements

Decorator Learning Summary

1. What is a decorator

A decorator is a wrapper syntax introduced in ES7 that can dynamically enhance classes or instance methods without the target being aware.

Readers interested can further study the Decorator Pattern.

In ES7, a decorator is just syntactic sugar, similar to class.

Refer to the Babel‑transformed ES5 code for details.

2. How to use decorators

2.1. On class methods

Decorators can be applied to class methods, as shown below:

function readonly(target, key, descriptor) {
    descriptor.writable = false;
    return descriptor;
}

class People {
    @readonly
    sayName() {
        console.log(this.name);
    }
}

var p = new People();
p.sayName = 'hello';

Running this code throws an error.

The decorator’s signature is function(target, key, descriptor) where:

target : the class prototype, e.g., People.prototype key : the property name, e.g., sayName descriptor : the property descriptor

This signature matches Object.defineProperty, making a method decorator essentially a wrapper around it.

2.2. On classes

Decorators can also enhance a class itself:

function nonTestable(target) {
    target.canTest = false;
}

@nonTestable
class People {}

console.log(People.canTest); // false

When applied to a class, only the class constructor is passed.

2.3. Decorator factories

When the same decorator needs different behavior on different targets, it can be written as a factory function:

function addName(name) {
    return function(target) {
        target.myName = name;
    };
}

@addName('people')
class People {
    static say() {
        console.log(People.myName);
    }
}

@addName('dog')
class Dog {
    static say() {
        console.log(Dog.myName);
    }
}

People.say(); // people
Dog.say(); // dog

3. How to enable decorators

Because decorators are an ES7 feature, Babel must be used to transpile them. Example .babelrc configuration:

{
  "presets": ["es2015", "stage-1"],
  "plugins": [
    "babel-plugin-transform-decorators-legacy"
  ]
}

Install the required packages:

npm i babel-cli babel-preset-es2015 babel-preset-stage-1 babel-plugin-transform-decorators

Then transpile:

babel index.js > index.es5.js

4. Practical applications

4.1. Implementing mixins

Example of using decorators as mixins:

function nameMixin(target) {
    target.prototype.setName = function(name) {
        this.name = name;
        return this;
    };
    target.prototype.sayName = function() {
        console.log(this.name);
    };
}

function ageMixin(target) {
    target.prototype.setAge = function(age) {
        this.age = age;
        return this;
    };
    target.prototype.sayAge = function() {
        console.log(this.age);
    };
}

@nameMixin
@ageMixin
class People {}

var p = new People();
p.setName('peter').sayName(); // peter
p.setAge(18).sayAge(); // 18

Compared with traditional mixin usage, decorators make the code clearer.

4.2. Simple AOP

Decorators can also implement Aspect‑Oriented Programming:

function aop(before, after) {
    return function(target, key, descriptor) {
        const method = descriptor.value;
        descriptor.value = (...args) => {
            let ret;
            before && before(...args);
            ret = method.apply(target, args);
            if (after) {
                ret = after(ret);
            }
            return ret;
        };
    };
}

function beforeTest1(opt) {
    opt.name = opt.name + ', haha';
}

function beforeTest2(...args) {}

function afterTest2(ret) {
    console.log('haha, add 10!');
    return ret + 10;
}

class Test {
    @aop(beforeTest1)
    static test1(opt) {
        console.log(`hello, ${opt.name}`);
    }

    @aop(beforeTest2, afterTest2)
    static test2(...args) {
        return args.reduce((a, b) => a + b);
    }
}

Test.test1({ name: 'peter' });
console.log(Test.test2(1, 2, 3));

The example shows how a decorator can run code before and after a method, resulting in clearer logic.

5. Summary

Decorators are an ES7 syntactic sugar that provide powerful, readable ways to extend classes and methods. Any code that follows the Decorator Pattern can be expressed with decorators, and Babel enables their use today.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptbabeldecoratorsES7
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.