Mastering JavaScript Decorators: From Python Concepts to ES6 Implementation

This article explains how decorators—originally popularized in Python—can be applied in JavaScript ES6, covering their syntax, class and property use cases, underlying mechanics with Object.defineProperty, and practical Babel transpilation steps.

Aotu Lab
Aotu Lab
Aotu Lab
Mastering JavaScript Decorators: From Python Concepts to ES6 Implementation

Introduction

ES6 added class and extends, but sharing or extending behavior across multiple classes can become unwieldy. Decorators offer a more elegant solution.

Python Decorators Recap

A Python decorator is a function that takes another function, extending the behavior of the latter function without explicitly modifying it.

Introduced in Python 2.4, decorators wrap existing functions or classes to add new behavior without altering the original code.

def decorator(f):
    print "my decorator"
    return f

@decorator
def myfunc():
    print "my function"

myfunc()  # prints "my decorator" then "my function"

The @decorator syntax shows how the wrapper runs before the original function.

Bringing Decorators to JavaScript

Before ES6, JavaScript developers manually added wrapper functions. With the decorator proposal (currently at stage 2), the syntax resembles Python, allowing annotations on classes and class members.

Basic Decorator Syntax in JavaScript

@decorator
class Cat {}

class Dog {
  @decorator
  run() {}
}

The @ symbol marks a decorator, which can target a class or a method.

Class Decorator Example

function isAnimal(target) {
  target.isAnimal = true;
  return target;
}

@isAnimal
class Cat {}

console.log(Cat.isAnimal); // true

This mirrors the Python example, adding a static property to the class.

Property (Method) Decorator Example

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

class Cat {
  @readonly
  say() { console.log("meow ~"); }
}

const kitty = new Cat();
kitty.say = function() { console.log("woof!"); };
kitty.say(); // still logs "meow ~"

When applied to a method, the decorator receives target, name, and descriptor. It modifies the descriptor (via Object.defineProperty) to make the method read‑only.

Underlying Mechanism

Decorators on properties ultimately call Object.defineProperty with a descriptor containing value, enumerable, configurable, and writable flags.

Object.defineProperty(Cat.prototype, "say", {
  value: function() { console.log("meow ~"); },
  enumerable: false,
  configurable: true,
  writable: true
});

By altering the descriptor, a decorator can enforce read‑only behavior, inject additional logic, or replace the original method.

Advanced Example: Enhancing a Method

function fast(target, name, descriptor) {
  target.speed = 20;
  const original = descriptor.value;
  descriptor.value = function() {
    original.call(this);
    console.log(`speed ${this.speed}`);
  };
  return descriptor;
}

class Rabbit {
  @fast
  run() { console.log("running~"); }
}

const bunny = new Rabbit();
bunny.run(); // logs "running~" then "speed 20"
console.log(bunny.speed); // 20

This decorator adds a speed property to the instance and wraps the original method to log the speed after execution.

Practical Usage and Transpilation

Because the decorator proposal is still a draft, most environments do not support it natively. Developers must use Babel with the legacy plugin:

babel --plugins transform-decorators-legacy es6.js > es5.js

After transpilation, the decorator logic is converted into standard ES5 code.

Conclusion

Decorators enable annotation and modification of classes and properties at design time, receiving target, name, and descriptor as arguments and optionally returning a new descriptor. While powerful, they require Babel for current browser compatibility.

References

https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841#.cmajiy3p1

https://github.com/wycats/javascript-decorators

http://www.artima.com/weblogs/viewpost.jsp?thread=240808

http://taobaofed.org/blog/2015/11/16/es7-decorator/

https://github.com/jayphelps/core-decorators.js

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.

frontendJavaScriptPythonprogrammingdecoratorses6
Aotu Lab
Written by

Aotu Lab

Aotu Lab, founded in October 2015, is a front-end engineering team serving multi-platform products. The articles in this public account are intended to share and discuss technology, reflecting only the personal views of Aotu Lab members and not the official stance of JD.com Technology.

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.