Playing Around with your Standard, Run-of-the-Mill JavaScript Decorator Example

JavaScript decorators have been a language feature since ES2015 came out, but they are still largely ‘experimental’ in JavaScript engines that support it. What are they? If you’re familiar with Java, you know how methods can be wrapped through annotations. The gist of it: a decorator wraps a JavaScript class method within another function, and it is invoked by annotation.

I’ll be using NodeJS for the example code, so there will be several modules, plugins, and configurations that are needed.


  1. initialize an npm project
  2. install the babel command-line tools; we’ll be needing this to transpile the decorated methods
  3. install plugins need for the transpilation
npm init -y
npm install --save babel-cli
npm install --save-dev babel-eslint babel-plugin-transform-decorators-legacy babel-polyfill babel-preset-env babel-register eslint eslint-plugin-node

4. Add a .babelrc file to your project with these settings:

"presets": ["env"],
"plugins": ["transform-decorators-legacy"]

Additional note: If you are using VSCode as an editor, go to Settings and turn on Experimental Decorators to make any warnings go away.

5. To run sample code, add the following run target in package.json:

"scripts": {
"start": "babel-node yourdecoratedcode.js --require babel-polyfill"

Standard Log Example

Then I’ll look at the ubiquitous @log example and later tweak it a bit. This is a plan vanilla decorator, of which you can find many variations.

The comments should make clear what is going on. The log function is the decorator, which wraps the class method that follows the decorator @log annotation. To use it, a class method is annotated with:

The console output shown as a comment at bottom comes from line 15 of the previous listing.

Logging with Parameter Names

With a little bit of digging, I was able to find code examples that illustrate a means of obtaining parameter names from a method signature. Now let’s have the decorator dump not just the parameter values, but the parameter names as well:

Adding Synthetic Parameters

You’re not actually limited to the arguments that you are given, but can infer parameter values from within the decorator, passing those onto the wrapped method. It may seem a little crazy, but I have found a use for this feature on a project I am working on.

The following decorator is going to infer by parameter name the argument values passed in. Instead of the decorator dumping a string to the console, I’ll have the wrapped function dump its parameter values.

This decorator will pass as arguments to the original function whatever is in MyClass.newStuff.isWombat and MyClass.newStuff.sugar at the time the function is called:

And the output is…

{ isWombat: true,
sugar: [ 'in the morning', 'in the evening', 'at suppertime' ] }
{ isWombat: true,
sugar: [ 'You are my candy, girl', 'and you keep me wanting you' ] }

Well, that wraps it up. Code repository can be found here.

read original article here