With the introduction of ES2015+, and as transpilation has become commonplace, many of you will have come across newer language features, either in real code or tutorials. One of these features that often has people scratching their heads when they first come across them are JavaScript decorators.
Decorators have become popular thanks to their use in Angular 2+. In Angular, decorators are available thanks to TypeScript, but they are due to be part of the ES2017 language update due out later this year. Let's take a look at what decorators are, and how they can be used to make your code cleaner and more easily understandable.
Note: If you're more of a video person, why not sign up for SitePoint Premium and check out some of our popular JavaScript courses?
What is a Decorator?
In its simplest form, a decorator is simply a way of wrapping one piece of code with another - literally "decorating" it.
This is a concept you might well have heard of previously as "Functional Composition", or "Higher-Order Functions".
This is already possible in standard JavaScript for many use cases, simply by calling one one function to wrap another:
function doSomething(name) {
console.log('Hello, ' + name);
}
function loggingDecorator(wrapped) {
return function() {
console.log('Starting');
const result = wrapped.apply(this, arguments);
console.log('Finished');
return result;
}
}
const wrapped = loggingDecorator(doSomething);
This example produces a new function - in the variable wrapped
- that can be called exactly the same way as the doSomething
function, and will do exactly the same thing. The difference is that it will do some logging before and after the wrapped function is called.
doSomething('Graham');
// Hello, Graham
wrapped('Graham');
// Starting
// Hello, Graham
// Finished
How to use JavaScript Decorators?
Decorators use a special syntax in ES2017, whereby they are prefixed with an @
symbol and placed immediately before the code being decorated.
Note: At the time of writing, the decorators are currently in "Stage 2 Draft" form, meaning that they are mostly finished but still subject to changes.
It is possible to use as many decorators on the same piece of code as you desire, and they will be applied in the order that you declare them.
For example:
@log()
@immutable()
class Example {
@time('demo')
doSomething() {
}
}
This defines a class and applies three decorators: two to the class itself and one to a property of the class:
- @log could log all access to the class.
- @immutable could make the class immutable - maybe it calls
Object.freeze
on new instances. - @time will record how long a method takes to execute and log this out with a unique tag.
At present, using decorators requires transpiler support, since no current browser or Node release has support for them yet.
If you are using Babel, this is enabled simply by using the transform-decorators-legacy plugin.
Note: the use of the word "legacy" in this Plugin is because it supports the way that Babel 5 handled Decorators, which might well be different to the final form when they are standardized.
Why use Decorators?
Whilst functional composition is already possible in JavaScript, it is significantly more difficult - or even impossible - to apply the same techniques to other pieces of code (e.g. classes and class properties).
The ES2017 draft adds support for class and property decorators that can be used to resolve these issues, and future JavaScript versions will probably add decorator support for other troublesome areas of code.
Decorators also allow for a cleaner syntax for applying these wrappers around your code, resulting in something that detracts less from the actual intention of what you are writing.
Different Types of Decorator
At present, the only types of decorator that are supported are on classes and members of classes. This includes properties, methods, getters, and setters.
Decorators are actually nothing more than functions that return another function, and that are called with the appropriate details of the item being decorated. These decorator functions are evaluated once when the program first runs, and the decorated code is replaced with the return value.
Continue reading %Exploring ES2017 Decorators in JavaScript%
by Graham Cox via SitePoint
No comments:
Post a Comment