美文网首页
Javascript Decorator

Javascript Decorator

作者: 四月白绵羊 | 来源:发表于2020-10-18 03:55 被阅读0次

    JS的 decorator 已经到了Stage 2 Draft的阶段。并且在 Babel 7得到支持

    修饰器其实在其他的语言中已经得到很完善的实现了,比如 Python。修饰器主要的功能是将辅助性的功能和核心功能分开。例如,核心功能可以是主营业务,辅助功能可以是身份验证,信息缓存或者日记功能。这些辅助功能大部分是可以共享的,并且和主要功能没有什么联系,所以解耦和重用是修饰器很重要的功能。

    相关信息

    不同类型修饰器的应用和分析

    类修饰器

    使用场景:为类添加静态属性或者方法。
    修饰器的参数:

    • target: 类本身

    例子:

    function language(value) {
        return function(target) {
            target.language = value;
        }
    }
    
    @language('English')
    class Country {}
    
    console.log(Country.language);
    # output: English
    
    实例方法修饰器

    应用场景:输出日志,性能计算,权限验证。
    修饰器的参数:

    • target:类的prototype。
    • name:要修饰的方法名称。
    • descriptor:该方法的修饰器。

    例子:

    function beforeFunc(target, name, descriptor) {
        const func = descriptor.value;
        const newFunc = function() {
            console.log(`Before calling: ${name}`);
            const result = func.apply(this, arguments);
            return result;
        }
        return {
            ...descriptor,
            value: newFunc
        }
    }
    
    function afterFunc(target, name, descriptor) {
        const func = descriptor.value;
        const newFunc = function() {
            const result = func.apply(this, arguments);
            console.log(`After calling: ${name}`);
            return result;
        }
        return {
            ...descriptor,
            value: newFunc
        }
    }
    
    class Medium {
        constructor() {
            this.base = 10;
        }
    
        @afterFunc
        @beforeFunc
        add(a, b){
            console.log(`Calculating...`);
            return a + b + this.base;
        }
    }
    
    // console.log(Country.language);
    
    const m = new Medium();
    console.log('Sum: ', m.add(1, 4));
    # Output:
    # Before calling: add
    # Calculating...
    # After calling: add
    # Sum:  15
    
    实例属性修饰器

    使用场景:修改property的属性(writable,enumerable,configurable等),监听属性的变化(watcher)。
    修饰器的参数:

    • target:类的prototype。
    • name:要修饰的方法名称。
    • descriptor:该方法的修饰器。

    Note: 使用数据描述符和存储描述符定义的属性,它们的descriptor是不一样的。

    例子:

    1. 存储描述符: 给属性添加监听器
    function observable(target, name, descriptor) {
        const setter = descriptor.set;
        return {
            ...descriptor,
            get: function() {
                console.log(`Before getting '${name}'. '${name}' is ${this.base}`);
                return this.base;
            },
            set: function(value) {
                console.log(`Before setting '${name}'. '${name}' is ${this.base}`);
                setter.call(this, value);
                return true;
            }
        };
    }
    
    class Medium {
        @observable
        get count () {
            return this.base;
        };
        set count (value) {
            this.base = value;
        };
    
        constructor() {
            this.base = 10;
        }
    }
    
    const m = new Medium();
    m.count += 20;
    console.log('Count: ', m.count);
    # Output:
    # Before getting 'count'. 'count' is 10
    # Before setting 'count'. 'count' is 10
    # Before getting 'count'. 'count' is 30
    # Count:  30
    
    1. 数据描述符: 将属性设置为只读
    function readonly(target, name, descriptor) {
        descriptor.writable = false;
        return descriptor;
    }
    class Medium {
        @readonly
        age = 18;
    }
    const m = new Medium();
    m.age = 28;
    
    # throw an error: 
    # TypeError: Cannot assign to read only property 'age' of object '#<Medium>'
    

    Desugar

    说到底JS中的修饰器只是一种语法糖,最终还是由解释器翻译成一般的JS语法。JS的修饰器主要依赖于 Object.defineProperty 功能,当解释器遇到了 @decorator 的语法时,就会调用这个修饰器函数对属性(方法)的描述符(descriptor)进行操作,然后将修饰过的 descriptor 重新定义属性。
    具体的转义可以查看:https://github.com/wycats/javascript-decorators#desugaring

    相关文章

      网友评论

          本文标题:Javascript Decorator

          本文链接:https://www.haomeiwen.com/subject/jhyqmktx.html