Class of

Many object-oriented languages have decorator functions that modify the behavior of a class

@testable
class MyTestableClass{}function testable(target){
    target.isTestable = true
}

MyTestableClass.isTestable  // true
Copy the code

The above code @testable is testable. It modifies the behavior of the MyTestableClass class by adding the static property isTestable to it. Testable functions target parameters from the MyTestableClass class itself. That is, a decorator is a function that processes a class. The first argument to the decorator function is the target class to be modified

If a parameter is not enough, you can wrap a function around the modifier

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

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

@testable(false)
class MyTestableClass{}
MyTestableClass.isTestable  // false
Copy the code

Modifiers change the behavior of classes at compile time, not run time.

If you want to add instance attributes, you can do so through the Prototype object of the target class

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

@testable
class MyTestableClass{}

let obj = new MyTestableClass();
obj.isTestable  // true
Copy the code

Method modification

Modifiers can modify not only classes but also class attributes

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

The readonly modifier modifies the name method of the class. The readonly modifier can take three arguments.

function readonly(target, name, descriptor){
    The original value of the // Descriptor object is as follows
  / / {
  // value: specifiedFunction,
  // enumerable: false,
  // configurable: true,
  // writable: true
  // };
  descriptor.writable = false;
  return descriptor;
}

readonly(Person.prototype, 'name', descriptor)
Copy the code

Prototype. The modifier is intended to modify the instance of the class, but this instance has not been generated yet, so we modify the prototype. The second parameter is the name of the property to be modified, and the third parameter is the description object of the property.

Execution of multiple modifiers

function dec(id){
	// This is done in the order of decoration
    console.log('evaluated', id);
    // The returned functions are executed in reverse order.
    return (target, property, descriptor) = > console.log('executed', id)
}

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

If the same method has multiple modifiers, it will be like peeling an onion, entering from the outside in and then executing from the inside out.

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