Decorator装饰器

来源:互联网 发布:日式衬衫知乎 编辑:程序博客网 时间:2024/06/03 20:31

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]}

更多文章

  • ECMAScript 6 常用特性整理
  • Promise-使用整理
  • Decorator装饰器
  • Iterator、Generator、async、await 异步编程