• ES6装饰器Decorator基本用法


    1. 基本形式

    @decorator
    class A {}
    
    // 等同于
    
    class A {}
    A = decorator(A);

    装饰器在javascript中仅仅可以修饰类和属性,不能修饰函数。
    装饰器对类的行为的改变,是代表编译时发生的,而不是在运行时。
    装饰器能在编译阶段运行代码。
    装饰器是经典的AOP模式的一种实现方式。

    2. 装饰器的执行顺序

    同一处的多个装饰器是按照洋葱模型,由外到内进入,再由内到外执行

    function dec(id){
        console.log('evaluated', id);
        return (target, property, descriptor) => console.log('executed', id);
    }
    
    class Example {
        @dec(1)
        @dec(2)
        method(){}
    }
    // evaluated 1
    // evaluated 2
    // executed 2
    // executed 1

    3. 常见的装饰器的例子

    1. 类可测试,添加一个属性

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

    若要进行更多的配置,可以使用高阶函数,增加参数,相当于一个工厂方法,用于生产特定类型的装饰器,例如:

    //testable是一个Factory
    function testable(isTestable) {
      return function(target) {
        target.isTestable = isTestable;
      }
    }
    
    @testable(true)
    class MyTestableClass {}
    MyTestableClass.isTestable // true
    
    @testable(false)
    class MyClass {}
    MyClass.isTestable // false

    2. 属性readonly装饰器

    class Person {
      @readonly
      name() { return `${this.first} ${this.last}` }
    }
    
    function readonly(target, name, descriptor){
      // descriptor对象原来的值如下
      // {
      //   value: specifiedFunction,
      //   enumerable: false,
      //   configurable: true,
      //   writable: true
      // };
      descriptor.writable = false;
      return descriptor;
    }

    3. 日志装饰器

    class Math {
      @log
      add(a, b) {
        return a + b;
      }
    }
    
    function log(target, name, descriptor) {
      var oldValue = descriptor.value;
    
      descriptor.value = function() {
        console.log(`Calling "${name}" with`, arguments);
        return oldValue.apply(null, arguments);
      };
    
      return descriptor;
    }
    
    const math = new Math();
    
    // passed parameters should get logged now
    math.add(2, 4);

    3. 实现memoize,备用录模式

    class Person {
      @memoize
      get name() { return `${this.first} ${this.last}` }
      set name(val) {
        let [first, last] = val.split(' ');
        this.first = first;
        this.last = last;
      }
    }
    
    let memoized = new WeakMap();
    function memoize(target, name, descriptor) {
      let getter = descriptor.get, setter = descriptor.set;
    
      descriptor.get = function() {
        let table = memoizationFor(this);
        if (name in table) { return table[name]; }
        return table[name] = getter.call(this);
      }
    
      descriptor.set = function(val) {
        let table = memoizationFor(this);
        setter.call(this, val);
        table[name] = val;
      }
    }
    
    function memoizationFor(obj) {
      let table = memoized.get(obj);
      if (!table) { table = Object.create(null); memoized.set(obj, table); }
      return table;
    }   

    参考:https://www.cnblogs.com/goloving/p/8001530.html
         https://www.cnblogs.com/whitewolf/p/details-of-ES7-JavaScript-Decorators.html

  • 相关阅读:
    python字符串连接方式(转)
    Python顺序与range和random
    将EXCEL中的列拼接成SQL insert插入语句
    Python OS模块
    Python3.5连接Mysql
    Mysql查看连接端口及版本
    Mysqldb连接Mysql数据库(转)
    Python 文件I/O (转)
    Python 日期和时间(转)
    Python序列的方法(转)
  • 原文地址:https://www.cnblogs.com/mengff/p/9661648.html
Copyright © 2020-2023  润新知