繁体   English   中英

使用非传统装饰器时如何装饰 JavaScript class 构造函数?

[英]How to decorate a JavaScript class constructor when using non-legacy decorators?

我有以下 class:

@log
class Example {
  constructor(name, age) {
    console.log("Example constructor", name, age);
    this.name = name;
    this.age = age;
  }
}

使用旧版装饰器时,这个@log装饰器:

function log(Class) {
  return class extends Class {
    constructor(...args) {
      console.log("log", args);
      super(...args);
    }
  };
}
// .babelrc
// ...
      "plugins": [
        ["@babel/plugin-proposal-decorators", { "legacy": true }],
        // ...
      ]
// ...

上面的设置效果很好,下面的代码:

const example = new Example("Graham", 34);

输出:

log (2) ["Graham", 34]
Example constructor Graham 34

现在,如何在使用非传统装饰器时获得相同的结果,即:

// .babelrc
// ...
      "plugins": [
        [
          "@babel/plugin-proposal-decorators",
          { "decoratorsBeforeExport": false }
        ],
        // ...
      ]
// ...

我如何实现@log以便它以与传统装饰器相同的方式工作?

function log(...args) {
  const [descriptor] = args;
  const { kind, elements } = descriptor;

  const newElements = elements.concat({
    kind: "method",
    placement: "prototype",
    key: "constructor",
    descriptor: {
      value: (...args) => {
        // I have tried this but it doesn't work...
        console.log("log", args);
      },
      configurable: true,
      writable: true,
      enumerable: true,
    },
  });

  return {
    kind,
    elements: newElements,
  };
}

我已经尝试了上面的代码,但它没有工作。 问题是我在使用非传统装饰器时没有对目标的引用。 你知道是否有一种方法可以实现与传统行为相同的行为?

谢谢你。

感谢BabelJS Slack 频道上的 loganfsmyth,我找到了答案。

您必须返回一个 object,其中包含一个名为 Finisher 的属性,该属性包含finisher ,例如:

function log(...args) {
  const [descriptor] = args;
  const { kind, elements } = descriptor;

  return {
    kind,
    elements,
    finisher: (Class) => {
      return class extends Class {
        constructor(...args) {
          console.log("log", args);
          super(...args);
        }
      };
    }
  };
}

然后在使用非传统装饰器时使用此代码:

@log
class Example {
  constructor(name, age) {
    console.log("Example constructor", name, age);
    this.name = name;
    this.age = age;
  }
}

const example = new Example("Graham", 34);

输出:

log (2) ["Graham", 34]
Example constructor Graham 34

与传统装饰器一样。

很难找到答案,因为@babel/plugin-proposal-decorators上没有记录非传统装饰器的这个特性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM