Free AI web copilot to create summaries, insights and extended knowledge, download it at here
8604
Abstract
<span class="hljs-keyword">const</span> boundFn = fn.<span class="hljs-title function_">bind</span>(<span class="hljs-variable language_">this</span>);
<span class="hljs-title class_">Object</span>.<span class="hljs-title function_">defineProperty</span>(<span class="hljs-variable language_">this</span>, key, {
<span class="hljs-attr">value</span>: boundFn,
<span class="hljs-attr">configurable</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">writable</span>: <span class="hljs-literal">true</span>,
});
<span class="hljs-keyword">return</span> boundFn;
},
};
}
<span class="hljs-keyword">class</span> <span class="hljs-title class_">MyComponent</span> {
<span class="hljs-title function_">constructor</span>(<span class="hljs-params">props</span>) {
<span class="hljs-variable language_">this</span>.<span class="hljs-property">props</span> = props;
}
@autobind
<span class="hljs-title function_">handleClick</span>(<span class="hljs-params"></span>) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">props</span>);
}
}</pre></div><p id="0013">In this example, the decorator is used to decorate the function so that it automatically binds this when called and returns a new function. This way, after instantiating , you don’t need to manually bind this when calling the function.<code>autobindhandleClickMyComponentthis.handleClick()</code></p><h1 id="3ffe">Logging</h1><p id="7a28">Decorators can be used to record logs, including printing information such as function calls, function execution times, etc.</p><div id="1a70"><pre><span class="hljs-keyword">function</span> <span class="hljs-title function_">log</span>(<span class="hljs-params">target, name, descriptor</span>) {
<span class="hljs-keyword">const</span> originalMethod = descriptor.<span class="hljs-property">value</span>;
descriptor.<span class="hljs-property">value</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">...args</span>) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">Function <span class="hljs-subst">${name}</span> called with <span class="hljs-subst">${args}</span></span>);
<span class="hljs-keyword">const</span> start = performance.<span class="hljs-title function_">now</span>();
<span class="hljs-keyword">const</span> result = originalMethod.<span class="hljs-title function_">apply</span>(<span class="hljs-variable language_">this</span>, args);
<span class="hljs-keyword">const</span> duration = performance.<span class="hljs-title function_">now</span>() - start;
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">Function <span class="hljs-subst">${name}</span> completed in <span class="hljs-subst">${duration}</span>ms</span>);
<span class="hljs-keyword">return</span> result;
};
<span class="hljs-keyword">return</span> descriptor
}
<span class="hljs-keyword">class</span> <span class="hljs-title class_">MyClass</span> {
@log
<span class="hljs-title function_">myMethod</span>(<span class="hljs-params">arg1, arg2</span>) {
<span class="hljs-keyword">return</span> arg1 + arg2;
}
}
<span class="hljs-keyword">const</span> obj = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyClass</span>();
obj.<span class="hljs-title function_">myMethod</span>(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>); <span class="hljs-comment">// Output: </span>
<span class="hljs-comment">// Function myMethod called with 1,2</span>
<span class="hljs-comment">// Function myMethod completed in 0.013614237010165215ms</span></pre></div><h1 id="aff7">Authentication authentication</h1><p id="bbff">Decorators can also be used to check a user’s authentication status and permissions to prevent unauthorized users from accessing sensitive data or performing actions on a regular basis.</p><div id="be1a"><pre><span class="hljs-keyword">function</span> <span class="hljs-title function_">authorization</span>(<span class="hljs-params">target, name, descriptor</span>) {
<span class="hljs-keyword">const</span> originalMethod = descriptor.<span class="hljs-property">value</span>;
descriptor.<span class="hljs-property">value</span> = <span class="hljs-keyword">function</span>(<span class="hljs-params">...args</span>) {
<span class="hljs-keyword">if</span> (!<span class="hljs-variable language_">this</span>.<span class="hljs-title function_">isAuthenticated</span>()) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">'Access denied! Not authenticated'</span>);
<span class="hljs-keyword">return</span>;
}
<span class="hljs-keyword">if</span> (!<span class="hljs-variable language_">this</span>.<span class="hljs-title function_">hasAccessTo</span>(name)) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">Access denied! User does not have permission to <span class="hljs-subst">${name}</span></span>);
<span class="hljs-keyword">return</span>;
}
<span class="hljs-keyword">return</span> originalMethod.<span class="hljs-title function_">apply</span>(<span class="hljs-variable language_">this</span>, args);
};
<span class="hljs-keyword">return</span> descriptor;
}
<span class="hljs-keyword">class</span> <span class="hljs-title class_">MyApi</span> {
<span class="hljs-title function_">isAuthenticated</span>(<span class="hljs-params"></span>) {
<span class="hljs-comment">// perform authentication check</span>
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
<span class="hljs-title function_">hasAccessTo</span>(<span class="hljs-params">endpoint</span>) {
<span class="hljs-comment">// perform authorization check</span>
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
@authorization
<span class="hljs-title function_">getUsers</span>(<span class="hljs-params"></span>) {
<span class="hljs-comment">// return users data</span>
}
@authorization
<span class="hljs-title function_">deleteUser</span>(<span class="hljs-params">id</span>) {
<span class="hljs-comment">// delete user with id</span>
}
}</pre></div><h1 id="646e">Cache</h1><p id="3465">Decorators can also be used to cache the execution results of functions to avoid double evaluation.</p><div id="5257"><pre><span class="hljs-keyword">function</span> <span class="hljs-title function_">memoize</span>(<span class="hljs-params">target, name, descriptor</span>) {
<span class="hljs-keyword">const</span> originalMethod = descriptor.<span class="hljs-property">value</span>;
<span class="hljs-keyword">const</span> cache = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Map</span>();
descriptor.<span class="hljs-property">value</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">...args</span>) {
<span class="hljs-keyword">const</span> cacheKey = args.<span class="hljs-title function_">toString</span>();
<span class="hljs-keyword">if</span> (cache.<span class="hljs-title function_">has</span>(cacheKey)) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">cache hit: <span class="hljs-subst">${cacheKey}</span></span>);
<span class="hljs-keyword">return</span> cache.<span class="hljs-title function_">get</span>(cacheKey);
}
<span class="hljs-keyword">const</span> result = originalMethod.<span class="hljs-title function_">apply</span>(<span class="hljs-variable language_">this</span>, args);
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">cache miss: <span class="hljs-subst">${cacheKey}</span></span>);
cache.<span class="hljs-title function_">set</span>(cacheKey, result);
<span class="hljs-keyword">return</span> result;
};
<span class="hljs-keyword">return</span> descriptor;
}
<span class="hljs-keyword">class
Options
</span> <span class="hljs-title class_">MyMath</span> {
@memoize
<span class="hljs-title function_">calculate</span>(<span class="hljs-params">num</span>) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'calculate called'</span>);
<span class="hljs-keyword">return</span> num * <span class="hljs-number">2</span>;
}
}
<span class="hljs-keyword">const</span> math = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyMath</span>();
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(math.<span class="hljs-title function_">calculate</span>(<span class="hljs-number">10</span>)); <span class="hljs-comment">// Output: </span>
<span class="hljs-comment">// calculate called</span>
<span class="hljs-comment">// cache miss: 10</span>
<span class="hljs-comment">// 20</span>
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(math.<span class="hljs-title function_">calculate</span>(<span class="hljs-number">10</span>)); <span class="hljs-comment">// Output: </span>
<span class="hljs-comment">// cache hit: 10</span>
<span class="hljs-comment">// 20</span></pre></div><h1 id="57d9">Aspect-oriented programming</h1><p id="0d61">Decorators can be used to implement facet-oriented programming, that is, to add functionality at runtime without modifying the original code.</p><div id="bc4d"><pre><span class="hljs-keyword">function</span> <span class="hljs-title function_">validate</span>(<span class="hljs-params">target, name, descriptor</span>) {
<span class="hljs-keyword">const</span> originalMethod = descriptor.<span class="hljs-property">value</span>;
descriptor.<span class="hljs-property">value</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">...args</span>) {
<span class="hljs-keyword">const</span> isValid = args.<span class="hljs-title function_">every</span>(<span class="hljs-function"><span class="hljs-params">arg</span> =></span> <span class="hljs-keyword">typeof</span> arg === <span class="hljs-string">'string'</span> && arg.<span class="hljs-property">length</span> > <span class="hljs-number">0</span>);
<span class="hljs-keyword">if</span> (!isValid) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">'Invalid arguments'</span>);
<span class="hljs-keyword">return</span>;
}
<span class="hljs-keyword">return</span> originalMethod.<span class="hljs-title function_">apply</span>(<span class="hljs-variable language_">this</span>, args);
};
<span class="hljs-keyword">return</span> descriptor;
}
<span class="hljs-keyword">class</span> <span class="hljs-title class_">MyForm</span> {
@validate
<span class="hljs-title function_">submit</span>(<span class="hljs-params">name, email, message</span>) {
<span class="hljs-comment">// submit the form</span>
}
}
<span class="hljs-keyword">const</span> form = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyForm</span>();
form.<span class="hljs-title function_">submit</span>(<span class="hljs-string">''</span>, <span class="hljs-string">'[email protected]'</span>, <span class="hljs-string">'Hello world'</span>); <span class="hljs-comment">// Output: Invalid arguments</span></pre></div><h1 id="c8da">Reversible decorators</h1><p id="5322">Decorators can also be applied in reversible scenes, for example, you can add a reversible decorator to modify function behavior.</p><div id="b868"><pre><span class="hljs-keyword">function</span> <span class="hljs-title function_">reverse</span>(<span class="hljs-params">target, name, descriptor</span>) {
<span class="hljs-keyword">const</span> originalMethod = descriptor.<span class="hljs-property">value</span>;
descriptor.<span class="hljs-property">value</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">...args</span>) {
args.<span class="hljs-title function_">reverse</span>();
<span class="hljs-keyword">return</span> originalMethod.<span class="hljs-title function_">apply</span>(<span class="hljs-variable language_">this</span>, args);
};
<span class="hljs-keyword">return</span> descriptor;
}
<span class="hljs-keyword">class</span> <span class="hljs-title class_">MyMath</span> {
@reverse
<span class="hljs-title function_">calculate</span>(<span class="hljs-params">num1, num2</span>) {
<span class="hljs-keyword">return</span> num1 + num2;
}
}
<span class="hljs-keyword">const</span> math = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyMath</span>();
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(math.<span class="hljs-title function_">calculate</span>(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)); <span class="hljs-comment">// Output: 3</span>
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(math.<span class="hljs-property">calculate</span>.<span class="hljs-title function_">reversed</span>(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)); <span class="hljs-comment">// Output: 3</span></pre></div><h1 id="2ddc">Automatic type checking</h1><p id="037c">Decorators can be applied to automatic type checking, for example, you can add a decorator to ensure that the type of a function parameter is correct.</p><div id="a63a"><pre><span class="hljs-keyword">function</span> <span class="hljs-title function_">checkType</span>(<span class="hljs-params">expectedType</span>) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">function</span>(<span class="hljs-params">target, name, descriptor</span>) {
<span class="hljs-keyword">const</span> originalMethod = descriptor.<span class="hljs-property">value</span>;
descriptor.<span class="hljs-property">value</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">...args</span>) {
<span class="hljs-keyword">const</span> invalidArgs = args.<span class="hljs-title function_">filter</span>(<span class="hljs-function"><span class="hljs-params">arg</span> =></span> <span class="hljs-keyword">typeof</span> arg !== expectedType);
<span class="hljs-keyword">if</span> (invalidArgs.<span class="hljs-property">length</span> > <span class="hljs-number">0</span>) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">`Invalid arguments: <span class="hljs-subst">${invalidArgs}</span>`</span>);
<span class="hljs-keyword">return</span>;
}
<span class="hljs-keyword">return</span> originalMethod.<span class="hljs-title function_">apply</span>(<span class="hljs-variable language_">this</span>, args);
};
<span class="hljs-keyword">return</span> descriptor;
}
}
<span class="hljs-keyword">class</span> <span class="hljs-title class_">MyMath</span> {
@<span class="hljs-title function_">checkType</span>(<span class="hljs-string">'number'</span>)
<span class="hljs-title function_">add</span>(<span class="hljs-params">num1, num2</span>) {
<span class="hljs-keyword">return</span> num1 + num2;
}
}
<span class="hljs-keyword">const</span> math = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyMath</span>();
math.<span class="hljs-title function_">add</span>(<span class="hljs-number">1</span>, <span class="hljs-string">'2'</span>); <span class="hljs-comment">// Output: Invalid arguments: 2</span></pre></div><p id="dd86"><i>More content at <a href="https://plainenglish.io/"><b>PlainEnglish.io</b></a>.</i></p><p id="5cf7"><i>Sign up for our <a href="http://newsletter.plainenglish.io/"><b>free weekly newsletter</b></a>. Follow us on <a href="https://twitter.com/inPlainEngHQ"><b>Twitter</b></a></i>, <a href="https://www.linkedin.com/company/inplainenglish/"><b><i>LinkedIn</i></b></a><i>, <a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><b>YouTube</b></a>, and <a href="https://discord.gg/GtDtUAvyhW"><b>Discord</b></a><b>.</b></i></p><p id="7057"><b><i>Interested in scaling your software startup</i></b><i>? Check out <a href="https://circuit.ooo?utm=publication-post-cta"><b>Circuit</b></a>.</i></p></article></body>