The leopard cat changes prince
During the reign of Emperor Zhenzong of the Northern Song Dynasty, there were two small masters, Imperial Concubine Li and Imperial concubine Liu, who both had dragons. Who ever thought that Concubine Liu was not a good person, the skin of the leopard cat for Li Concubine just gave birth to the child. The day is pitiable, perform the task of the palace woman humanity not min, the child to eight xian king to raise, this just leads to later, Bao Zheng Chen state put food to save Li Fei, Renzong recognized mother family reunion. Yeah, well, that’s a good talk about decorator patterns and that’s a good story. Everyone don’t worry, this front end decorator mode to achieve the core is actually in these five words, the sky to float five words, that is not a matter, string of string…… The core is actually on these five words — leopard cat for prince.
Decorator pattern
Let’s cut to the chase and get down to business. The decorator pattern is a type of design pattern that is a way to dynamically add more functionality to existing functionality. It mainly reflects the single responsibility principle and the open and close principle among the six principles of design mode. Single responsibility is easy to understand, it’s concentration, it’s a function that does only one thing. The open closed principle means open for extension, closed for modification.
In human terms, we need to add functions and requirements on the premise that the original functions remain unchanged, not to change the written functions, but to find ways to expand them. The idea is the decorator pattern.
Simplest implementation
Now let’s start with the simplest implementation. Consider the following scenario, where you define a start function that prints “start” when executed.
let start = function () {
console.log('start')
}
start();
Copy the code
Well, now that the product is here, he said that before it can start, it needs to include a self-check. The fastest way to do this, of course, is to add a check code to the start function. But this violates the single responsibility principle and the open closed principle of design patterns. This is where the decorator pattern comes in.
let start = function () {
console.log('start')
}
const _start = start;
start = function(){
console.log('check');
_start()
}
start();
Copy the code
We didn’t make any changes to the original function, so we don’t have to worry about affecting the original function. First assign the address of the original function object to the new variable, and then override the original function variable. The overwritten function first adds the self-check function and then executes the original function backed up to the new variable above. This implements one of the simplest decorator patterns. You taste, you fine taste, there is no leopard cat for the taste of prince.
Decorator pattern and agent pattern
With that in mind, you should have some idea of the decorator pattern. So let’s strike while the iron is hot and get to know the decorator model’s cousin, the agent model. The proxy pattern is also one of the classic design patterns and has in common with the decorator pattern that it does not change the original function. The proxy mode determines access to the original functionality and is a form of control. The decorator mode determines what you can access to the original functionality with what other features added. If the analogy is to be made, then the agent is a bit like a firewall, and the decorator is a bit like the various packages of the express you buy.
In ES6, a new standard built-in object, Proxy, is an implementation of the Proxy pattern. You may already know that in Vue3.0, Proxy will be used instead of Object. DefineProperty for data response.
grammar
let p = new Proxy(target, handler);
Copy the code
A target is a target object wrapped in a Proxy (it can be any type of object, including a native array, a function, or even another Proxy). Handler is an object whose properties are functions that define the behavior of the agent when an operation is performed. Proxy supports 13 kinds of interception operations, covering almost all aspects of the operation of object functions, which is enough to open a new topic, so I won’t extend it here.
Decorator patterns and aspect oriented programming
Aspect oriented programming, like object oriented programming, is a kind of programming idea and a supplement to object oriented programming. One of the features of Spring, the Java framework used for back-end development, is AOP, aspect oriented programming. So what is an aspect, if it’s a back-end development understanding, there are a lot of other terms that need to be introduced, but we have KOA on the front end, we have the Onion model. The onion model is a slice.
My function methods are the core of the onion. I want to do some things before and after a method call, such as logging, timing, etc., so I wrap up our function methods and add another layer, which is called aspect oriented programming. You’re thinking about where the program is executing. While object-oriented programming allows us to easily abstract and manage our code, aspect oriented programming focuses on decoupling and reuse. Decorators are one way to implement aspect – oriented programming.
Source code level implementation
Function. Before and function. After
Before Webpack and Babel, the classic AOP implementations were function.before and function.after, and we can also use them to implement the decorator pattern.
Function.prototype.before = function(fn){ var _this = this; Return function(){return function(){return function(){return function(){return function(); The new function refers to fn fn. Apply (this,arguments); // Execute the new function return _this.apply(this,arguments); }} function.prototype. after = Function (fn){var _this = this; return function(){ var r = _this.apply(this,arguments); Func_1 fn. Apply (this,arguments); // Return r; } } var func_1 = function () { console.log("2") } func_1 = func_1.before(function () { console.log("1"); }).after(function () { console.log("3"); } ) func_1(); // Output 1, 2, 3Copy the code
Object.defineProperty()
Later, we had Webpack and Babel. Object.defineproperty () is used to directly define a new property on an Object, or to modify an existing property.
*/ object.defineProperty (obj, prop, desc) */ object.defineProperty (obj, prop, desc)Copy the code
Attribute descriptors include data descriptors: value, writable; Access descriptors: GET, set; Descriptor: signals, Enumerable; The access descriptors GET and set are the basis of the VUE framework, and the data descriptors are the basis of the Babel implementation decorators.
Babel finally converts our @ function name to
Object["define" + "Property"](target, property, desc);
Copy the code
As you can see, the decorator method is essentially implemented using object.defineProperty ().
function before(target, key, descriptor) { const fn = descriptor.value; return { ... descriptor, value() { console.log('before') return fn.apply(this, arguments); } } } function after(target, key, descriptor) { const fn = descriptor.value; return { ... descriptor, value() { let result = fn.apply(this, arguments); console.log('after'); return result; } } } class Test { @after @before func(){ console.log('func') } } const test = new Test(); test.func();Copy the code
Run after Babel compilation and output: before func after
Engineering implementation
Take the WebPack project as an example. If you haven’t used decorators in a WebPack project, there is room for improvement in development efficiency and code refactoring. If you are using Babel6, install and configure the Babel plugin babel-plugin-transformer-decorators-Legacy. If you are using Babel7, Install and configure the official plugin @babel/plugin-proposal-decorators. After the configuration is completed, the functions unrelated to business in the project can be implemented by means of decorators, such as login condition judgment, anti-shaking, throttling, buried point statistics, etc.
What a great decorator looks like
Core-decorators is a third party module that provides common decorators. By learning it, we can better understand decorators. It’s dead simple address is https://github.com/jayphelps/core-decorators, there are 4.2 K of praise.
The welfare of
Article in the “big turn FE” public number will be sent, and the public number has a raffle, this article prize is around a commemorative T-shirt or around a random hand, choose one, welcome to pay attention to the ✿✿, °▽°) blue ✿