Good decorator source code to learn the second play

This is the 27th day of my participation in Gwen Challenge

preface

Previous article: good decorator source code learning (a) : time

@ Deprecate, @readOnly, @Enumerable, @non64x

deprecate

Used to indicate that the XX API/ method has been deprecated

Use the sample

A warning that the API has been deprecated can be thrown at function execution with a simple @deprecate as follows

Where “deprecate” has the same effect as “deprecated” but a different alias

export { default as deprecate, default as deprecated } from './core/deprecate'
Copy the code
import { deprecate, deprecated } from '.. /index'
class Test {
    @deprecate(a)sayHello1() {
        console.log('hello 1');
    }
    @deprecated('API deprecation Warning ')
    sayHello2() {
        console.log('hello 2');
    }
    @deprecate('API deprecation Warning ', {url:'https://www.baidu.com'})
    sayHello3() {
        console.log('hello 3'); }}const t = new Test()
t.sayHello1()
t.sayHello2()
t.sayHello3()
Copy the code

perform

The function structure

Passing in parameters:

  • MSG: There is default content
  • Options: Further specify document links through url attributes
const DEFAULT_MSG = 'This function will be removed in future versions.';

interfaceOptions{ url? :string
}

export default function deprecate(msg = DEFAULT_MSG, options:Options = {}) {
    return function (target, key, descriptor) {}}Copy the code

Finally realize

const DEFAULT_MSG = 'This function will be removed in future versions.';

interfaceOptions{ url? :string
}

export default function deprecate(msg = DEFAULT_MSG, options:Options = {}) {
    return function (target, key, descriptor) {
        If the object being decorated is not a function, an error is thrown
        if (typeofdescriptor.value ! = ='function') {
            throw new SyntaxError('Only functions can be marked as deprecated');
        }

        // Generate method signature (reaction from xx class xx method)
        const methodSignature = `${target.constructor.name}#${key}`;

        // If the address document on the cable describes the cause, display the address
        if (options.url) {
            msg += `\n\n    See ${options.url} for more details.\n\n`;
        }

        return {
            ...descriptor,
            value: function deprecationWrapper() {
                // Prints a warning message
                console.warn(`DEPRECATION ${methodSignature}: ${msg}`);
                // Execute the function
                return descriptor.value.apply(this.arguments); }}; }}Copy the code

readonly

Makes the specified property read-only, that is, the content of the property cannot be changed after instantiation

Use the sample

Using the following, you can make the target property read-only with a simple @readonly

import { readonly } from '.. /index';
class Test {
    hello1(){
        console.log('hello1');
    }

    @readonly
    hello2(){
        console.log('hello2'); }}const t = new Test();
t.hello1 = function(){
    console.log('1');
}

t.hello1()

t.hello2 = function(){
    console.log('2');
}

t.hello2()
Copy the code

perform

function

You can change the writable property of a decorator object descriptor to false without passing additional parameters

export default function readonly(target, key, descriptor) {
    descriptor.writable = false
    return descriptor
}
Copy the code

Enumerable, nonEnumerable, Enumable

Change the enumerable property value of the decorator object

Use the sample

import enumable from ".. /core/enumable";
import enumerable from ".. /core/enumerable";
import nonenumerable from ".. /core/nonenumerable";

class Test {
    @nonenumerable
    a(){}@enumerable
    b(){}@enumable(false)
    c(){}}console.log(Object.getOwnPropertyDescriptor(Test.prototype,'a')? .enumerable ===false); // true
console.log(Object.getOwnPropertyDescriptor(Test.prototype,'b')? .enumerable ===true);  // true
console.log(Object.getOwnPropertyDescriptor(Test.prototype,'c')? .enumerable ===false); // true

console.log(Object.keys(Test.prototype)); // ['b']
Copy the code

implementation

The easy way to do this is to change the Enumerable value of the decoration object

enumerable

export default function enumerable(target, key, descriptor) {
    descriptor.enumerable = true
    return descriptor
}
Copy the code

nonenumerable

export default function nonenumerable(target, key, descriptor) {
    descriptor.enumerable = false
    return descriptor
}
Copy the code

enumable

export default function enumable(v = true) {
    return function (target, key, descriptor) {
        descriptor.enumerable = v
        return descriptor
    }
}
Copy the code

nonconfigurable

Sets the decorative object’s 64x property to false

The descriptor of this property can be changed and deleted from the corresponding object only if and if the 64x works without any additional information.

Use the sample

import { nonconfigurable } from ".. /index";

class Test {
    @nonconfigurable
    a(){}b(){}}let prototype:any = Test.prototype
delete prototype.b
console.log(Object.keys(Test.prototype)); // ['a']
delete prototype.a // Cannot delete property 'a' of #
      
console.log(Object.keys(Test.prototype));
Copy the code

implementation

This is also a simple way to modify the different value of the decorative object

export default function nonconfigurable(target, key, descriptor) {
    descriptor.configurable = false
    return descriptor
}
Copy the code

To be continued

The next one will learn:

  • @mixin: Blends methods into classes
  • @lazyInitialize: Initializes target properties only when they are used
  • @debounce: if you
  • @throttle: the throttle