{
    "componentChunkName": "component---src-templates-blog-post-tsx",
    "path": "/blog/2017-06-01-one-helpful-way-to-think-about-javascript-decorators/",
    "result": {"data":{"blogPost":{"title":"One Helpful Way to Think About JavaScript Decorators","slug":"/blog/2017-06-01-one-helpful-way-to-think-about-javascript-decorators/","authorNodes":[{"name":"Charles Lowell","slug":"/people/charles-lowell/"}],"markdown":{"html":"<p>Why Decorators?</p>\n<p>It is an important question; one many tutorials rush past in their hurry to talk about the <em>what</em> and <em>how</em>. Of course, after being exposed to enough doses of <em>what</em> and <em>how</em>, you can usually piece together <em>why</em>, but in my experience it saves time to just hear it up front. I'd like to share one of the ways I've come to think about decorators and how it's helped me think about when to use them.</p>\n<p>So like every good meta-discussion of JavaScript, let's start by\ntalking about Clojure. Don't sweat it if you don't know Clojure,\nthat's totally <em>ok</em>. The examples are very simple and only there to\nillustrate a bigger point.</p>\n<p>Anyway, back to Clojure...</p>\n<p>In Clojure, one way to associate a name with a value is to use the <code class=\"language-text\">def</code> form:</p>\n<div class=\"gatsby-highlight\" data-language=\"clojure\"><pre class=\"language-clojure\"><code class=\"language-clojure\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">def</span> message <span class=\"token string\">\"hello computer\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>After that declaration, subsequent code can refer to the string <code class=\"language-text\">\"hello computer\"</code> just by using the symbol <code class=\"language-text\">message</code> instead.</p>\n<p>The ability to associate names and values is a pretty handy thing in programmming, and it turns out you can do something very similar in JavaScript too. You might write something like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> message <span class=\"token operator\">=</span> <span class=\"token string\">\"hello computer\"</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Another thing that Clojure has support for is function values:\nfunctions that can be passed as either an argument to, or the return\nvalue from, another function. You can declare a function value that\nadds its operands together with the following syntax.</p>\n<div class=\"gatsby-highlight\" data-language=\"clojure\"><pre class=\"language-clojure\"><code class=\"language-clojure\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">fn</span> <span class=\"token punctuation\">[</span>x y<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">+</span> x y<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Not to be outdone though, JavaScript also has support for first class functions, and it's syntax is even a little more concise than Clojure's too! This is it here.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token punctuation\">(</span><span class=\"token parameter\">x<span class=\"token punctuation\">,</span> y</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> x <span class=\"token operator\">+</span> y<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span></code></pre></div>\n<p>Both of these are examples of <em>anonymous functions</em>. Function values that can be passed around as one-offs to other functions. It's handy, but sometimes it's not enough.</p>\n<p>Often what we want is to associate a name with a function so that we\ncan call it again and again. In the same way we associated the name\n<code class=\"language-text\">message</code> with the string value <code class=\"language-text\">\"hello computer\"</code> so that we could\naccess it repeatedly just by referring to <code class=\"language-text\">message</code>, we can associate\na function value with a symbol so that we can reach for it over and\nover just by remembering its name. To do that, we use the two\nconstructs just introduced (<code class=\"language-text\">def</code> and <code class=\"language-text\">fn</code>):</p>\n<div class=\"gatsby-highlight\" data-language=\"clojure\"><pre class=\"language-clojure\"><code class=\"language-clojure\"><span class=\"token comment\">;; associate the symbol `add` with the function to add</span>\n<span class=\"token punctuation\">(</span><span class=\"token keyword\">def</span> add <span class=\"token punctuation\">(</span><span class=\"token keyword\">fn</span> <span class=\"token punctuation\">[</span>x y<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">+</span> x y<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token comment\">;; and now we can call it by name.</span>\n<span class=\"token punctuation\">(</span><span class=\"token function\">add</span> <span class=\"token number\">1</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">;;=> 2</span>\n<span class=\"token punctuation\">(</span><span class=\"token function\">add</span> <span class=\"token number\">4</span> <span class=\"token number\">3</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">;;=> 7</span></code></pre></div>\n<p>Just like before, a parallel construct exists in JavaScript. No suprises there.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// associate the symbol `add` with the function to add</span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">add</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">x<span class=\"token punctuation\">,</span> y</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> x <span class=\"token operator\">+</span> y<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// and now we can call it by name.</span>\n<span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">//=> 2</span>\n<span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">//=> 7</span></code></pre></div>\n<p>But of course, this pattern of associating a name with a function is so prevalent that both Clojure and JavaScript have a special syntax to both declare a function <em>and</em> associate it with a name in one fell swoop. In Clojure you use <code class=\"language-text\">defn</code> (literally the conjuction of <code class=\"language-text\">def</code> + <code class=\"language-text\">fn</code>)</p>\n<div class=\"gatsby-highlight\" data-language=\"clojure\"><pre class=\"language-clojure\"><code class=\"language-clojure\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">defn</span> add <span class=\"token punctuation\">[</span>x y<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">+</span> x y<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>And you're probably already familiar with how it's done in JavaScript with a <code class=\"language-text\">function</code> declaration.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">x<span class=\"token punctuation\">,</span> y</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> x <span class=\"token operator\">+</span> y<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span></code></pre></div>\n<h2 id=\"theres-a-point-to-this-i-promise\" style=\"position:relative;\"><a href=\"#theres-a-point-to-this-i-promise\" aria-label=\"theres a point to this i promise permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>There's a point to this. I promise.</h2>\n<p>So I just explained named functions in both Clojure and JavaScript. Big\nwhoop.</p>\n<p>It's such a simple idea and an equally simple mechanism. And on the surface they seem equivalent in both languages, but there's one key difference between the way the named function syntax works in JavaScript and the way it works in Clojure. Both syntaxes declare a function value, and both associate that function value with a name so that it can be referred to later.</p>\n<p>The <em>difference</em> is that in JavaScript the syntax is implemented by the JavaScript parser and interpreter, whereas in Clojure the syntax is implemented in Clojure.</p>\n<h2 id=\"a-macro-says-what\" style=\"position:relative;\"><a href=\"#a-macro-says-what\" aria-label=\"a macro says what permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>A Macro Says What?</h2>\n<p>That bears repeating. In JavaScript, the syntax is implemented by the\nJavaScript parser and interpreter. More than likely that means baked\nin with some C or C++ code somewhere. Beyond the implementation, it\nmeans that there needs to be a\n<a href=\"http://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">specification for the syntax as part ECMA standard</a>\nso that any of the multiple engines can be sure to get it right.</p>\n<figure class=\"figure\" alt=\"a picture of the twenty seven line specification of function syntax in BNF format on the Ecma website\">\n  <img class=\"figure-img img-fluid\" src=\"/img/2017-06-01-one-helpful-way-to-think-about-javascript-decorators_function-syntax.png\">\n  <figcaption class=\"figure-caption\"> <em><strong>Figure 1:</strong> Put this in your C++ and smoke it</em></caption>\n</figure>\n<p>Contrast this to Clojure in which the named function syntax is nothing but more Clojure code. It's easy to understand not only for programmers, but also for any alternative implementation of Clojure (such as clojurescript). It's a nifty trick that saves time, adds clarity and eliminates ambiguity. How does it work? The answer is macros.</p>\n<p>Macros are powerful, but they aren't fancy. A macro is just a function like any other function, and if you can work with functions, then you can work with macros.</p>\n<p>There are two things that make a macro function special though. The\nfirst is that the type of its arguments and the type it returns are\nnot general values <em>but source code</em>. That means it takes code in as\nits input, and returns code as it's output. Here's a couple of\nfamiliar functions along with their (pseudo) types for comparison. <code class=\"language-text\">map</code> takes an array as its input, and returns another array. <code class=\"language-text\">sum</code> takes an array as input, and returns a number. <code class=\"language-text\">defn</code> takes code input and returns more code.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">map :: Array -> Array\nsum :: Array -> Number\ndefn :: Code -> Code</code></pre></div>\n<p>The second thing that makes a macro function special is that it doesn't run when the rest of your program does; it runs when your program is being compiled. When the compiler encounters a macro, it calls it, and then replaces the macro with the code that got returned.</p>\n<figure class=\"figure\" alt=\"the arguments to a macro function are the unevaluated source code\">\n  <img class=\"figure-img img-fluid\" src=\"/img/2017-06-01-one-helpful-way-to-think-about-javascript-decorators_defn-arguments.png\">\n  <figcaption class=\"figure-caption\"> <em><strong>Figure 2:</strong> The arguments to a macro function are unevaluated source code</em></caption>\n</figure>\n<p>In fact, this is how the <code class=\"language-text\">defn</code> macro works. It literally replaces</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">(defn add [x y] (+ xy))</code></pre></div>\n<p>with</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">(def add (fn [x y] (+ x y)))</code></pre></div>\n<figure class=\"figure\" alt=\"defn consumes its arguments and returns\n  new source code containing those arguments\">\n  <img class=\"figure-img img-fluid\" src=\"/img/2017-06-01-one-helpful-way-to-think-about-javascript-decorators_defn-mapping.png\">\n  <figcaption class=\"figure-caption\"> <em><strong>Figure 3:</strong>\n  The defn macro takes code as arguments and returns more code</em></caption>\n</figure>\n<p>The point here is not to geek out too hard on Clojure macros, but to\nshow just how much more you can do with so much less when your\nlanguage has first class support for transforming code into other\ncode. Large swaths of what we think of as Clojure syntax is actually\ndefined with Clojure. The syntax it does have baked in works\nharder. There's no need to change the way the compiler works, and\n<em>certainly</em> no slog through a potentially contentious\n<a href=\"https://github.com/tc39/ecma262#ecmascript\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">specification by committee</a>.</p>\n<p>Wouldn't it be nice if JavaScript let us do something similar? Wouldn't it be nice if we could extend JavaScript syntax with just a few lines of JavaScript code instead of years spent shit-posting on the internet?</p>\n<h2 id=\"decorators-to-the-rescue\" style=\"position:relative;\"><a href=\"#decorators-to-the-rescue\" aria-label=\"decorators to the rescue permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Decorators to the rescue</h2>\n<p>The answer is that with decorators we can... almost. To be clear, decorators are <em>not</em> lisp macros. They're less powerful and they operate in a much smaller niche. But even so, they're an exciting development because there is just enough overlap with macros to make them helpful in the same kinds of situations.</p>\n<p>That's because, like a macro, a decorator is also <em>just a function</em>. And also like a macro, it's a function that operates on code <em>before</em> the rest of your program sees it.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@decorator :: Code -> Code</code></pre></div>\n<p>Like a macro, we can use this to add the new syntax we always wanted to our JavaScript classes.</p>\n<p>For example, I've often wished that there were an <code class=\"language-text\">immutable</code> keyword in JavaScript that made it impossible to change member data of an instance once it was constructed. Wouldn't it be great if you write a class like this?</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">immutable <span class=\"token keyword\">class</span> <span class=\"token class-name\">Circle</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">radius</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius <span class=\"token operator\">=</span> radius<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">get</span> <span class=\"token function\">area</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> Math<span class=\"token punctuation\">.</span><span class=\"token constant\">PI</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius <span class=\"token operator\">*</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">let</span> circle <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Circle</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\ncircle<span class=\"token punctuation\">.</span>area <span class=\"token comment\">//=> 25π</span>\n\n<span class=\"token comment\">// can't do this!</span>\ncircle<span class=\"token punctuation\">.</span>radius <span class=\"token operator\">=</span> <span class=\"token number\">10</span> <span class=\"token comment\">//=> Error!</span></code></pre></div>\n<p>I think that would be awesome, and if you feel the way I do, then you've got two options:</p>\n<p>A. Begin your submission to the TC39 (you'd better get on it if you\nwant to hit your deadline in three weeks!)</p>\n<p>B. Do it now with decorators.</p>\n<p>Decorators can help us get the syntax we want today because they let\nyou transparently transform the code that you <em>see</em> into the code that\nyou <em>want</em>. In the case of our <code class=\"language-text\">immutable</code> keyword, the code is a\nclass. In other words, we want to take the class that we <em>see</em>\n(mutation allowed) and convert it into the class we <em>want</em> (no\nmutation allowed)</p>\n<p>The class we <em>see</em> has this constructor:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Circle</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">radius</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius <span class=\"token operator\">=</span> radius<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>But the class we <em>want</em> has this constructor:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">Circle</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">radius</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius <span class=\"token operator\">=</span> radius<span class=\"token punctuation\">;</span>\n    Object<span class=\"token punctuation\">.</span><span class=\"token function\">freeze</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>If we can write a function that takes the former and returns the latter, then we're in business. Luckily, this is pretty straightforward. In order to make an immutable version of any given class, we can extend it, and then make a call to <code class=\"language-text\">Object.freeze</code> after invoking the original constructor.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// @immutable :: Class -> Class</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">immutable</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">Class</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">class</span> <span class=\"token class-name\">ImmutableVersion</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Class</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token operator\">...</span>args</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span><span class=\"token operator\">...</span>args<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      Object<span class=\"token punctuation\">.</span><span class=\"token function\">freeze</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> ImmutableVersion<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>We now have a function that returns an immutable version of any class, and so now we can just use it as a decorator; almost like we were creating our own syntax.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">@immutable <span class=\"token keyword\">class</span> <span class=\"token class-name\">Circle</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">radius</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius <span class=\"token operator\">=</span> radius<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">get</span> <span class=\"token function\">area</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> Math<span class=\"token punctuation\">.</span><span class=\"token constant\">PI</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius <span class=\"token operator\">*</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Our JavaScript interpreter will see this and transparently convert the <code class=\"language-text\">Circle</code> class that we see into a different one; one that prohibits any mutation of its member data after construction.</p>\n<p>Decorators aren't just for entire classes. They can be used to enhance individual members of as class as well and transform them transparently into something more powerful. For example, since the <code class=\"language-text\">area</code> of the circle is a computed property, it won't be enumerable by default.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">Object<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Circle</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">//=> ['radius']</span></code></pre></div>\n<p>That doesn't seem quite right. Shouldn't <code class=\"language-text\">area</code> be in there too?</p>\n<p>What would be really nice if if JavaScript had a keyword to make any property enumerable. E.g.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token punctuation\">{</span>\n  enumerable <span class=\"token keyword\">get</span> <span class=\"token function\">area</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> Math<span class=\"token punctuation\">.</span><span class=\"token constant\">PI</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius <span class=\"token operator\">*</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>It doesn't of course, but with decorators we can change that. We'll\njust write a member decorator: a decorator that operates on\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">property descriptors</a>\ninstead of classes. We can write an <code class=\"language-text\">enumerable</code> function to take the property descriptor we <em>see</em> (non-enumerable) and return the property descriptor we <em>want</em> (enumerable). This is accomplished simply enough by returning a new descriptor exactly like the old one, except with the enumerable key of the descriptor set to <code class=\"language-text\">true</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// @enumerable :: Property -> Property</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">enumerable</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">target<span class=\"token punctuation\">,</span> key<span class=\"token punctuation\">,</span> descriptor</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span><span class=\"token operator\">...</span>descriptor<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">enumerable</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>With this in hand, we can mark the <code class=\"language-text\">area</code> property as enumerable, just as though the syntax had existed the whole time.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">@immutable <span class=\"token keyword\">class</span> <span class=\"token class-name\">Circle</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">radius</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius <span class=\"token operator\">=</span> radius<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  @enumerable <span class=\"token keyword\">get</span> <span class=\"token function\">area</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> Math<span class=\"token punctuation\">.</span><span class=\"token constant\">PI</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius <span class=\"token operator\">*</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>radius<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Declared this way, circles will let you know that they have an area in addition to a radius:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">Object<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Circle</span><span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">//=> ['radius', 'area']</span></code></pre></div>\n<p>Easy!</p>\n<h2 id=\"decorators-ftw\" style=\"position:relative;\"><a href=\"#decorators-ftw\" aria-label=\"decorators ftw permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Decorators FTW</h2>\n<p>And that's it! My goal with this brief tour of decorators isn't to\nshow you the ins and outs of how they work, but to share a helpful way\nto think about them and when they might be the right tool to reach\nfor. While decorators are not lisp macros, it's useful to think about\nthem as a spiritual grandchild in the sense that their biggest power\nis to <em>transform the primary artifacts of your code before the rest of\nyour program sees them</em>. Rather being locked into a given syntax, the\ninterpreter is open to extension, and you can negotiate with it for a\nnew set of semantics.</p>\n<p>In a way, by including decorators and allowing them to stand in for\nmany of the use-cases where a new syntax might otherwise be desirable,\nthe ECMAScript specification is firing itself from its primary\nresponsibility of evolving the core language. What previously might\nhave taken months or years, can now be done in a matter of minutes or\nhours; a huge roadblock gone that has historically stood in the way of progress.</p>\n<p>For individual developers, decorators let us work with a lighter touch; applying just a little bit of new syntax to make big transformations, but all the while preserving the core intent and readability of our code.</p>\n<hr/>\n<p>I’m Charles Lowell (<a href=\"https://twitter.com/cowboyd\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@cowboyd</a> on twitter), and I build UI for a\nliving at <a href=\"http://frontside.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Frontside</a>. If you enjoyed this, I’d love to hear\nfrom you. We're always <a href=\"http://frontside.com/careers/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">hiring</a> and\nlooking for <a href=\"http://frontside.com/services/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">exciting new work</a></p>","frontmatter":{"date":"June 01, 2017","description":"JavaScript decorators are coming, but what are the class of problems which they're useful for? In this brief tour of decorators, we'll try to answer that question by contrasting them with comparable technology from other languages.","tags":["javascript","clojure","macros","decorators"],"img":{"childImageSharp":{"fixed":{"src":"/static/5bdaef2c99b94bac1ebfbfce229c49b9/a6352/2017-06-01-one-helpful-way-to-think-about-javascript-decorators_russian-dolls.jpg"}}}}}}},"pageContext":{"id":"9bc500f9-d2ce-5648-946e-1ef27bdbac02"}},
    "staticQueryHashes": ["1241260443"]}