Decorator装饰器

Decorator 修饰器

说明

由 ES2017 引入了这个功能,他是一个函数用来修改类的行为,解决了不同类之间共享方法的问题

修饰器对类的行为的改变是在代码编译时发生的,而不是在运行时,本质就是编译时执行的函数

由于存在变量提升,使得修饰器不能用于函数(包括构造函数),类不会提升所以不会有这个问题

基本使用


    @decorator  
    class Test {
        constructor(name) {
            this.name = name;
        }
    }

    function decorator (target) {
        // target 就是需要被修饰的类
        target.prototype.getName = function () {
            console.log(this.name);
        }
    }

    const test = new Test('xiaobai');
    test.getName(); // xiaobai

修饰器通过封装后接受其他参数

    function addMethod(methods) {
        return function (target) {
            Object.assign(target.prototype, methods);
        }
    }

    const methods = {
        change: function () {console.log('change')},
        add: function () {},
        delete: function () {},
        get: function () {}
    }

    @addMethod(methods)
    class Test {}

    const test = new Test();

    test.change(); // change

修饰器可以修饰类中的方法

作用在方法上的 decorator 接受的第一个参数是类的 prototype;作用到类上的 decorator 第一个参数表示类本身

Decorators 的本质是利用了 ES5 的 Object.defineProperty 属性,所以它的三个参数:target name descriptor 跟 Object.defineProperty 的参数是一致的

Object.defineProperty 的参数详解看这里

  • target:需要修饰的类的原型 prototype
  • name: 需要修饰的类的属性名或者方法名
  • descriptor:被修改的属性的描述符
    • configurable:true | false 表示对象的属性是否可以被删除,以及除 writable 特性外的其他特性是否可以被修改
    • enumerable:true | false 定义被修改的属性是否可以是可以枚举的
    • value:此属性对应的值(数值、对象、函数等)
    • writable:true | false 是否可以重写此属性
    • initializer:如果修饰器修饰的是一个属性不是方法,则会有这个属性出现代替 value
    function log (target, name, descriptor) {
        // 保留旧的方法
        const tempFn = descriptor.value;

        // 重新定义方法
        descriptor.value = function () {
            console.log(`this is ${name} arguments: `, arguments);
            // 借用旧的方法
            return tempFn.apply(this, arguments);
        }

        return descriptor;
    }

    class Test {
        constructor() {
            this.list = []
        }

        @log
        add (...items) {
            this.list.push(...items);
        }
    }

    var test = new Test();
    test.add(12, 33, 222);
    // 修饰器打印的日志
    // this is add arguments:  (3) [12, 33, 222, callee: (...), Symbol(Symbol.iterator): function]
    console.log(test); // {list: [12, 33, 222]}

修饰器修饰属性

    function change(target, name, descriptor) {
        const tempVal = descriptor.initializer();
        console.log(descriptor.initializer);
        /*
            initializer 函数类型
            function initializer() {
                return 'def value';
            }
        */
        descriptor.initializer = function () {
            return 'change ' + tempVal;
        }
        return descriptor;
    }


    class Test {

        @change
        def = 'def value'
    }

    const test = new Test();
    console.log(test.def) // change def value

修饰器可以叠加使用

    function log (order) {
        return function (target, name, descriptor) {
            const tempFn = descriptor.value;

            descriptor.value = function () {
                console.log('decorator ' + order);
                return tempFn.apply(this, arguments);
            }

            return descriptor;
        }
    }

    class Test {
        constructor() {
            this.list = []
        }

        @log('top')
        @log('bottom')
        add (...items) {
            this.list.push(...items);
        }
    }

    var test = new Test();
    test.add(12, 33, 222);
    // decorator top | decorator bottom
    console.log(test); // {list: [12, 33, 222]}

更多文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值