Es 6——Decoratorクラスの修飾器

10344 ワード

修飾器(Decorator)はクラスの動作を修飾するための関数であり、ES 2017ではこの機能が導入されている.現在babelトランスコーダはクラスにとって、JavaScriptコードの静的解析の重要なツールとしてクラスにのみ使用され、関数には使用できない(関数に昇格があるため、クラスは昇格しない)
  • 修飾器によるクラスの動作の変更は、実行時ではなくコードコンパイル時に発生する.これは、修飾器がコンパイル段階でコードを実行できることを意味する、すなわち、修飾器自体がコンパイル時に実行される関数
  • である.

    クラスの修飾:


    修飾子の最初のパラメータは、修飾するターゲットクラスです.
      @testable
      class Fun {}
    
      function testable (target) {
        target.add = true
      }
    
      console.log(Fun.add)// true
    

    パラメータが足りないと思ったら、外部で関数を再カプセル化できます.
      @testable(true)
      class Fun {}
    
      function testable (value) {
        return function (target) {
          target.add = value
        }
      }
    
      console.log(Fun.add)// true
    

    メソッドの修飾

      class Person {
        @readonly
        name () {
          return `${this.first} ${this.last}`
        }
      }
    
      // readonly        name   
      //              ,              ,              
      function readonly (target, name, descriptor) {
        // descriptor         
        /*{
          value:specifiedFunction,
          enumerable:false,
          configurable:true,
          writable:true
        }*/
        descriptor.writable = false
        return descriptor
      }
    
      readonly(Person.prototype, 'name', descriptor)
      //    
      Object.defineProperty(Person.prototype, 'name', descriptor)
    

    @log修飾器は出力ログとして機能します
      class Math {
        @log
        add (a, b) {
          return a + b
        }
      }
    
      function log (target, name, descriptor) {
        let oldValue = descriptor.value
    
        descriptor.value = function () {
          //         true
          
          // Calling "add" with Arguments(2) [2, 4, callee: (...), Symbol(Symbol.iterator): ƒ] true
          console.log(`Calling "${name}" with`, arguments)
          
          // oldValue: function add(a, b) {return a + b;}
          console.log(`oldValue: ${oldValue}`)
          
          return oldValue.apply(null, arguments)
        }
    
        return descriptor
      }
    
      const math = new Math()
      math.add(2, 4)
    
  • 上のコードから分かるように、Personクラスはテスト可能であり、nameメソッドは読み取り専用で枚挙にいとまがない.
  • 同じ方法に複数の修飾器がある場合、その方法はまず外から内へ修飾器に入り、その後、内から外へ
  • を実行する.
  • 例えばreadonly修飾器が先に入るが、nonenumerable修飾器は
  • を先に実行する.
      @testable
      class Person {
        @readonly
        @nonenumerable
        name () {return `${this.first} ${this.last}`}
      }
    

    推薦:core-decorators.jsは、サードパーティ製モジュールで、いくつかの一般的な修飾器を提供し、修飾器をよりよく理解することができます.