JavaScript decorator Speed Guide

This article is reproduced in: Ape 2048 Website ➝ https://www.mk2048.com/blog/blog.php?id=hj1jk2cb0j


Decorators JavaScript is ES7 new features added. Typescript students should be familiar with earlier access to this feature, TypeScript? Had earlier supported the use Decorators, but also provides support for ES5's. ?? article? Decorators will do a detailed explanation, I believe you will experience it for programming convenience and elegance.

Before I do a full-time front-end development, he is a professional .NET programmers for .NET in the "Features" use very familiar. Written in the class, method or property on a bracket, which brackets initialize a characteristic, it will have an impact on the behavior of class, method or property. This is particularly useful in AOP programming, as well as ORM framework, just as magic. But when JavaScript is no such feature. Decorators in use for the first time in TypeScript, because we want the entire application? Contextual information about the program to make a sequence of treatment, need a simple way, in the original domain model? Marked with a label to identify whether or serialized serialization of behavior control, such a scenario Decorators play its power. Then we need to reconstruct our state management, switch between variable class definition and application of immutable objects, if Decorators, whether from the convenience of series or decoupling point of view have had a surprising effect. Decorators have been trying to sort out related to the use of a common document, the simplest way to explain this topic, I have not write. Accidentally discovered an article on the network (https://cabbageapps.com/fell-love-js-decorators/), exactly match the content and wording of this article I want to express,? Then take? Come and do it again editing and adaptation. Like to see? English students can click on the link to read the original.

1.0 Decorator

If we direct search "decorators" or "decorator" in the search engine results and related programming, you will see the introduction of design patterns in the decorator pattern.

More intuitive examples are as follows:

WeaponAccessory figure above is a decorator, they add? Additional methods and familiar to the base class. It does not matter if you do not understand, follow me step by step to achieve your? Own decorator, will naturally understand. The picture below, can help you intuitively understand decorator.

5.gif

We simply understand decorator, it can be considered a package of objects, methods, familiar? Packaging. When we need to access an object, if we pass this package to access the periphery of the object, then, is this package? Attached behavior will be triggered. For example? Added a silencer gun. Muffler is a decoration, but it turned out the gun as a whole, opened fire when the muffler will play a role. ?

From the perspective of object-oriented concept is well understood. So how do we use decorator in JavaScript?

1.1 Tour start Decorators

Decorators are ES7? Only support new? Characteristics, but with Babel and TypesScript, we can now use it, this paper TypesScript example.

First modify tsconfig.json files, settings experimentalDecorators and emitDecoratorMetadata to true.

{
  "compilerOptions": {
    "target": "es2015",
    "module": "commonjs",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true
  },
  "exclude": [
    "node_modules",
  ]
}

We start with the effect to start, and then layers of analysis. Look at the following piece of code:

function leDecorator(target, propertyKey: string, descriptor: PropertyDescriptor): any {
    var oldValue = descriptor.value;

    descriptor.value = function() {
      console.log(`Calling "${propertyKey}" with`, arguments,target);
      let value = oldValue.apply(null, [arguments[1], arguments[0]]);

      console.log(`Function is executed`);
      return value + "; This is awesome";
    };

    return descriptor;
  }

  class JSMeetup {
    speaker = "Ruban";
    //@leDecorator
    welcome(arg1, arg2) {
      console.log(`Arguments Received are ${arg1} ${arg2}`);
      return `${arg1} ${arg2}`;
    }
  }

  const meetup = new JSMeetup();

  console.log(meetup.welcome("World", "Hello"));

? Run the above code, the results are as follows:

Let's modify the code, the comment line 17 release.

Run the code again, the results are as follows:

Note that the output image above the left, and the right side shows the code? Line number. We can now? Sure, then added @leDecorator label, function welcome behavior has changed,? Where is leDecorator trigger a change of function. According to our basic understanding on the face of the decorator, we can think leDecorator be welcome decorators. Between the decorator and the decorator connected by @ operator .

In JavaScript we have the level of emotional understanding of the decorator,? Our code is a decorative function. In JavaScript, a total of four categories decorator?:

  • Method Decorator function decorator
  • Property Decorators familiar decorator
  • Class Decorator class decorator
  • Parameter Parameter Decorator decorator

? Here we break one by one! Come on!

1.2 function decorator

The first to be compromised decorator is a function decorator, this section is the core content of this article, we will explain to function decorator to? Insight into the nature of JavaScript Decorators.

By using the function decorators, we can control the input and output functions.

Here is the definition of a function of decorator:

MethodDecorator = <T>(target: Object, key: string, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | Void;

? Just follow the above definition, we can customize a function decorator, meaning three parameters as follows:

  • target -?> decorated objects
  • key -> decorated function name
  • descriptor -.> attribute descriptor is transmitted over the properties may be viewed by Object.getOwnPropertyDescriptor attribute descriptor () method.

About attribute descriptor can refer to more detailed information https://www.jianshu.com/p/19529527df80.

Simply put, the property descriptor can be used to configure a property of an object return value, get / set behavior, can be removed, can be modified, it can be enumerated characteristics. In order to understand that you can smooth decorator, below we look at? A little intuitive example.

Open the browser console, enter the following code?:

var o, d;
var o = { get foo() { return 17; }, bar:17, foobar:function(){return "FooBar"} };

d = Object.getOwnPropertyDescriptor(o, 'foo');
console.log(d);
d = Object.getOwnPropertyDescriptor(o, 'bar');
console.log(d);
d = Object.getOwnPropertyDescriptor(o, 'foobar');
console.log(d);

The results are as follows:

Here we define an object o, defines three properties --foo, bar and foobar, then? Obtained by Object.getOwnPropertyDescriptor ()? Each attribute descriptor and print them out. Let's do a brief description of the value, enumerable, configurable and writable.

  • value -> Return values ​​literal or function / property calculations.
  • enumerable -> Can be enumerated (if you can be enumerated in (for x in obj) cycle out?)
  • configurable - whether> attributes can be configured
  • writable -?> whether the property is writable.

Each method has its own property or a descriptor, we can modify the behavior of the property by the descriptor or return value. The following key here:

Essence decorator is modified descriptor

It is time to write a decorator hands up.

1.2.1? Decorators instance method

Here we modify the input and output of a function by a method decorators.

function leDecorator(target, propertyKey: string, descriptor: PropertyDescriptor): any {
    var oldValue = descriptor.value;

    descriptor.value = function() {
      console.log(`Calling "${propertyKey}" with`, arguments,target);
      // Executing the original function interchanging the arguments
      let value = oldValue.apply(null, [arguments[1], arguments[0]]);
      //returning a modified value
      return value + "; This is awesome";
    };

    return descriptor;
  }

  class JSMeetup {
    speaker = "Ruban";
    //@leDecorator
    welcome(arg1, arg2) {
      console.log(`Arguments Received are ${arg1}, ${arg2}`);
      return `${arg1} ${arg2}`;
    }
  }

  const meetup = new JSMeetup();

  console.log(meetup.welcome("World", "Hello"));

? Decorators when not in use, the output value:

Arguments Received are World, Hello
World Hello

When enabled decoration, the output value:

Calling "welcome" with { '0': 'World', '1': 'Hello' } JSMeetup {}
Arguments Received are Hello, World
Hello World; This is awesome

We see that the output value of hair became the method changes. Now we see the method decorators defined by parameters, leDecorator get the name of the calling object at the time of execution? Decorated method? Parameters are descriptors decorating method. First saved by oldValue variables? Method descriptor of the original value, that is the way we welcome defined. Next, descriptor.value been reassigned.

In the new function first calls the original function, to obtain the return value, and then modify the return value. Finally return descriptor, the new descriptor will be applied to welcome method, this time integrating function body has been replaced.

By using a decorator, we realized the original packaging function, you can modify the input and output method, which means that we can apply a variety of desired magic effect on the target method.

Here are a few places to note:

  • Decoration is executed when the class is declared, not class instantiation.
  • The method returns a value decorator
  • Storing the original descriptor and returns a new descriptor is the recommended approach. This is useful in a multi-scene descriptor applications.
  • Descriptor set value, do not use the arrow functions.

Now we have completed and understood the first method decorator. Here we come to the school property decorator.

1.3 Properties decorator

Properties and methods decorator decorator is very similar, decorators through the property, we can use to redefine getters, setters, modify enumerable, configurable attributes.

Decorator attribute is defined as follows:

PropertyDecorator = (target: Object, key: string) => void;

Parameters as follows:

  • target: property owners
  • key: attribute name

Before using the specific properties decorator, let's take a brief look at Object.defineProperty method. Object.defineProperty method is often used to give a dynamic objects? Add or modify properties. The following is a sample:

var o = { get foo() { return 17; }, bar:17, foobar:function(){return "FooBar"} };

Object.defineProperty(o, 'myProperty', {
get: function () {
return this['myProperty'];
},
set: function (val) {
this['myProperty'] = val;
},
enumerable:true,
configurable:true
});

The above test debugging console code.

From the results, we see that the use of Object.defineProperty, we add dynamic objects are added to the property. Let based Object.defineProperty to implement a simple property decorator.

function realName(target, key: string): any {
    // property value
    var _val = target[key];

    // property getter
    var getter = function () {
      return "Ragularuban(" + _val + ")";
    };

    // property setter
    var setter = function (newVal) {
      _val = newVal;
    };

    // Create new property with getter and setter
    Object.defineProperty(target, key, {
      get: getter,
      set: setter
    });
  }

  class JSMeetup {
    //@realName
    public myName = "Ruban";
    constructor() {
    }
    greet() {
      return "Hi, I'm " + this.myName;
    }
  }

  const meetup = new JSMeetup();
  console.log(meetup.greet());
  meetup.myName = "Ragul";
  console.log(meetup.greet());

? When NA decorator, output is:

Hi, I'm Ruban
Hi, I'm Ragul

After you enable decorator, the result is:

Hi, I'm Ragularuban(Ruban)
Hi, I'm Ragularuban(Ragul)

Is not it simple? Followed by Class decorator.

1.4 Class decorator

Class is decorated by the operation of the Class constructor to dynamically add properties and methods and modifications of the Class. Here is the definition of Class decorators:

ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction;

ClassDecorator receive only one parameter, the Class constructor. The following sample code, modify the properties of the original Speaker class, and adds a dynamic attribute extra.

function AwesomeMeetup<T extends { new (...args: any[]): {} }>(constructor: T) {
    return class extends constructor implements extra {
      speaker: string = "Ragularuban";
      extra = "Tadah!";
    }
  }

  //@AwesomeMeetup
  class JSMeetup {
    public speaker = "Ruban";
    constructor() {
    }
    greet() {
      return "Hi, I'm " + this.speaker;
    }
  }

  interface extra {
    extra: string;
  }

  const meetup = new JSMeetup() as JSMeetup & extra;
  console.log(meetup.greet());
  console.log(meetup.extra);

In the case where the output is not enabled decorative value:

In the case of decorator enabled, the output is:

It should be noted that the constructor is called only once .

Now I come to learn last decorator, decorator parameters.

1.5 Parameters decorator

If the parameter to infer the role of decorator by decorators have said above, it might be to modify the parameters, but in fact not the case. Decorators parameters are often used to mark specific parameters, and reads the corresponding tag in the process decorator, further action. E.g:

function logParameter(target: any, key: string, index: number) {
    var metadataKey = `myMetaData`;
    if (Array.isArray(target[metadataKey])) {
      target[metadataKey].push(index);
    }
    else {
      target[metadataKey] = [index];
    }
  }

  function logMethod(target, key: string, descriptor: any): any {
    var originalMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {

      var metadataKey = `myMetaData`;
      var indices = target[metadataKey];
      console.log('indices', indices);
      for (var i = 0; i < args.length; i++) {

        if (indices.indexOf(i) !== -1) {
          console.log("Found a marked parameter at index" + i);
          args[i] = "Abrakadabra";
        }
      }
      var result = originalMethod.apply(this, args);
      return result;

    }
    return descriptor;
  }

  class JSMeetup {
    //@logMethod
    public saySomething(something: string, @logParameter somethingElse: string): string {
      return something + " : " + somethingElse;
    }
  }

  let meetup = new JSMeetup();

  console.log(meetup.saySomething("something", "Something Else"));

The above code, we have defined a parameter decorator, which will be decorated decoration parameters into a specified array. In the method decorator, find the parameter labeled the case further treatment is not enabled decorators, the following output?:

Decorators enabled, the output results are as follows:

1.6 Summary

Now that we have learned to use all the decorators, the following summarize the key usage?:

  • The core method is a method decorator descriptor
  • Core attributes decorator is Object.defineProperty
  • Core Class is the constructor decorator
  • The main parameters of the role of decorator is labeled, to be used in conjunction with methods decorators

More good front end of the text, concern micro-channel subscription number "mysterious soul studio" reply "qd" to

Mysterious soul studio
Here is a reference article: https://www.typescriptlang.org/docs/handbook/decorators.html

https://github.com/Microsoft/TypeScript-Handbook/blob/master/pages/Decorators.md

https://survivejs.com/react/appendices/understanding-decorators/

https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841

https://blog.wolksoftware.com/decorators-metadata-reflection-in-typescript-from-novice-to-expert-part-ii https://github.com/arolson101/typescript-decorators


More professional front-end knowledge, make the [2048] ape www.mk2048.com

Guess you like

Origin www.cnblogs.com/jiangshangbulao/p/11780564.html