article This originally appeared on dormoshe.io Decorators are one of my favorite features in ECMAScript. The ease of use and easy to build make them so popular. They are clean. They are simple. They are cool. They are here to stay. Now you can use them, and you don’t want to ignore them. Most of the developers use decorators, but they don’t know what they are and how to build them. The first time I really met the decorators was when , in September 2016 — do you remember? 😍. They look at me, I look on them and it was love at first sight. Angular 2 was landed In this article, we will understand what they are, how to build them and why we don’t need to be afraid of them. We will see how to build the . rich logger decorators from my previous article One moment, what is a Decorator? A decorator is just a function. Decorators make it possible to annotate and modify classes and properties at design time. A Decorator is a special kind of declaration that can be attached to a class declaration, method, property, or parameter. Decorators use the form @expression, where expression must evaluate to a function that will be called at run-time with information about the decorated declaration. Case Study In this section we will see how to build some parts of the project. rich-logger-decorator Logger Decorator The @ decorator is a method decorator. Log messages will be printed before the function will start and after the function will end. This decorator can get options that define the behavior of the flow. Logger Full logger decorator code Because of the options argument, this decorator needs to return a function (so this is a decorator factory). A decorator has a signature like that . method function(target, methodName, descriptor) It takes 3 arguments: — the original method being decorated. target — the name of the method being decorated. methodName — a property descriptor of the given property if it exists on the object, undefined otherwise. The property descriptor is obtained by invoking the function. descriptor Object.getOwnPropertyDescriptor() The first part of the function tries to fetch the descriptor, for some edge cases (for the decorator): ClassLogger Logger decorator code — part I The second part is the fetching of the original method by accessing the value of the descriptor: Logger decorator code — part II The third part is the monkey patch of the original method: Logger decorator code — part III As you can see one message is being logged by the mechanism before the original method call and one after the call. The function called with the source arguments call and the result returned by the new method. In the last part, we mark the method as monkey patched method (will be used later in the decorator) and return the descriptor to support using of more decorators for this method. ClassLogger Logger decorator code — part IV @ClassLogger The decorator is a method decorator. When you put the decorator on top of the class definition, all the methods in the class are logged automatically (except methods that are decorated by ). @ClassLogger @DisableLogger Full class logger decorator code As Logger decorator, this is also a decorator factory. A decorator has a signature like that . The target is a reference to the class constructor. class function(target) The decorator needs to decorate the requested methods — all the class methods being decorated, unless the array option will be set. After it’s set — only the methods in the array will be decorated. loggedMethodsNames Full class logger decorator code — part I This code fetches the properties of the class (including the class methods). Then they were filtered using the array option. loggedMethodsNames Full class logger decorator code — part II Now, loop over the filtered items. If the item is not a function or its already decorated by the logging mechanism (according to ), the item is omitted. __loggerMonkeyPatchCompleted Full class logger decorator code — part III And now we “monkey patched” these methods like in the method Logger decorator. That’s it. @DisableLogger The decorator is also a method decorator. The decorator will skip this method from being logged. @DisableLogger ClassLogger Disable logger decorator code For this purpose, we just need to change the boolean value and that’s it. This is an example for a simple decorator that doesn’t change the original method. References article Rich Typescript Logger Decorators for Easy Coding GitHub repository rich-logger-decorator in npm rich-logger-decorator Conclusion Decorators are amazing. They improve readability and reusability. You can compile them to ES5 with Typescript, Traceur or Bable. And now you know how to build them, so go and code your custom decorators and don’t forget to share… You can follow me on dormoshe.io or Twitter to read more about Angular, JavaScript and web development.
Share Your Thoughts