Home  >  Article  >  Web Front-end  >  How to understand es6 decorators

How to understand es6 decorators

青灯夜游
青灯夜游Original
2023-01-03 16:14:142179browse

In es6, the decorator pattern is a design theory that dynamically extends the functions of an object without changing the original class and using inheritance; the essence of the decorator is an ordinary function, used for extension Class attributes and class methods. Advantages of using decorators: 1. The code becomes more readable, and the decorator naming is equivalent to a comment; 2. The original functions can be expanded without changing the original code.

How to understand es6 decorators

The operating environment of this tutorial: Windows 7 system, ECMAScript version 6, Dell G3 computer.

How to understand Decorator in ES6?

Decorator, that is, decorator, from its name, it is easy for us to think of the decorator pattern

Simply speaking, the decorator pattern is a method that does not change the original Classes and the design theory of dynamically extending object functionality using inheritance.

The same is true for the Decorator function in ES6. Its essence is not a tall structure, it is just an ordinary function used to extend class attributes and class methods

A soldier is defined here. He has no equipment.

class soldier{ 
}

Define a function to get AK equipment, that is, the decorator

function strong(target){
    target.AK = true
}

Use the decorator to enhance the soldier

@strong
class soldier{
}

At this time, the soldier has Weapon

soldier.AK // true

Although the above code is simple, we can clearly see the two major advantages of using Decorator:

  • The readability of the code becomes stronger. The decorator naming is equivalent to a comment

  • Expand the original function without changing the original code

Usage of decorator

Docorator modified objects are the following two types:

  • Class decoration

  • Decoration of class attributes

Decoration of class

When decorating the class itself, it can accept one parameter, that is, the class itself

Decompose the decorator behavior so that everyone can have a deeper understanding

@decorator
class A {}

// 等同于

class A {}
A = decorator(A) || A;

The following @testable is a decorator, and the target is the incoming class, that is MyTestableClass implements adding static attributes to classes

@testable
class MyTestableClass {
  // ...
}

function testable(target) {
  target.isTestable = true;
}

MyTestableClass.isTestable // true

If you want to pass parameters, you can encapsulate a layer of functions outside the decorator

function testable(isTestable) {
  return function(target) {
    target.isTestable = isTestable;
  }
}

@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true

@testable(false)
class MyClass {}
MyClass.isTestable // false

Decoration of class attributes

When decorating class attributes, it can accept three parameters:

  • Prototype object of the class

  • Required Decorated attribute name

  • Description object of decorated attribute name

First define a readonly decorator

function readonly(target, name, descriptor){
  descriptor.writable = false; // 将可写属性设为false
  return descriptor;
}

Use readonly decoration The name method of the class

class Person {
  @readonly
  name() { return `${this.first} ${this.last}` }
}

is equivalent to the following call

readonly(Person.prototype, 'name', descriptor);

If a method has multiple decorators, just like an onion, first enter from the outside to the inside, and then execute from the inside to the outside

function dec(id){
    console.log('evaluated', id);
    return (target, property, descriptor) =>console.log('executed', id);
}

class Example {
    @dec(1)
    @dec(2)
    method(){}
}
// evaluated 1
// evaluated 2
// executed 2
// executed 1

The outer decorator @dec(1) enters first, but the inner decorator @dec(2) executes first

Note

Decorators cannot be used to decorate functions because there are variable declarations in the function.

var counter = 0;

var add = function () {
  counter++;
};

@add
function foo() {
}

During the compilation phase, it becomes the following

var counter;
var add;

@add
function foo() {
}

counter = 0;

add = function () {
  counter++;
};

The intention is that counter is equal to 1 after execution. But in fact the result is that counter is equal to 0

Usage scenarios of decorator

Based on the powerful function of Decorator, we can complete various scenarios Requirements, here is a brief list of several:

When using react-redux, if it is written in the following form, it is both unsightly and troublesome

class MyReactComponent extends React.Component {}

export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);

It becomes much simpler through the decorator

@connect(mapStateToProps, mapDispatchToProps)
export default class MyReactComponent extends React.Component {}

Mixins can also be written as decorators to make their use more concise

function mixins(...list) {
  return function (target) {
    Object.assign(target.prototype, ...list);
  };
}

// 使用
const Foo = {
  foo() { console.log('foo') }
};

@mixins(Foo)
class MyClass {}

let obj = new MyClass();
obj.foo() // "foo"

Let’s talk about several common decorators in core-decorators.js

@antobind

The autobind decorator makes the this object in the method bind the original object

import { autobind } from 'core-decorators';

class Person {
  @autobind
  getPerson() {
    return this;
  }
}

let person = new Person();
let getPerson = person.getPerson;

getPerson() === person;
// true

@readonly

readonly The decorator makes a property or method unwritable

import { readonly } from 'core-decorators';

class Meal {
  @readonly
  entree = 'steak';
}

var dinner = new Meal();
dinner.entree = 'salmon';
// Cannot assign to read only property 'entree' of [object Object]

@deprecate

The deprecate or deprecated decorator displays a warning on the console indicating that the method will be deprecated

import { deprecate } from 'core-decorators';

class Person {
  @deprecate
  facepalm() {}

  @deprecate('功能废除了')
  facepalmHard() {}
}

let person = new Person();

person.facepalm();
// DEPRECATION Person#facepalm: This function will be removed in future versions.

person.facepalmHard();
// DEPRECATION Person#facepalmHard: 功能废除了

[Related recommendations: javascript video tutorial, web front-end]

The above is the detailed content of How to understand es6 decorators. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn