如何使用和应用 JavaScript 装饰器?

Posted

技术标签:

【中文标题】如何使用和应用 JavaScript 装饰器?【英文标题】:How do I use and apply JavaScript decorators? 【发布时间】:2018-06-11 20:27:20 【问题描述】:

我正在尝试了解如何在一段非常简单的代码中使用装饰器,因此我可以将这个概念应用到我更大的项目中。借鉴 Addy Osmani 的文章 here,我创建了一段简单的代码,如下所示。

比如说,我有一个名为Cat 的类,有一个meow() 方法,我想用一些日志来装饰它,如下所示。

class Cat 
  @logger
  meow()  console.log( ' Meeeoow! ') 
;


function logger(target, key, descriptor) 
  console.log("Cat snarling...");
  return descriptor;


const cat = new Cat();
cat.meow();

当我尝试对 Node.js 解释器(版本 9.1.0)执行此操作时,我收到以下错误。

/Users/ravindranath/projects/decorators/index.js:2 @logger ^ SyntaxError:无效或意外的令牌 在 createScript (vm.js:80:10) 在 Object.runInThisContext (vm.js:152:10) 在 Module._compile (module.js:605:28) 在 Object.Module._extensions..js (module.js:652:10) 在 Module.load (module.js:560:32) 在 tryModuleLoad (module.js:503:12) 在 Function.Module._load (module.js:495:3) 在 Function.Module.runMain (module.js:682:10) 启动时(bootstrap_node.js:191:16) 在 bootstrap_node.js:613:3

所以,我的问题是:

    Node.js 9.x 是否支持装饰器语法?还是会在未来的某个版本中出现?

    我在 GitHub 上看到了一些基于 express-js 的装饰器,但我无法弄清楚如何创建自己的装饰器。有人可以提供一个使用 Node.js 创建自定义装饰器的简单基本示例吗?

【问题讨论】:

你可以在这里查看node.green 我写了一篇关于如何快速入门的短文 - dev.to/dpkshrma/… 【参考方案1】:

装饰器不是 ECMAScript 2016(又名 7)的一部分。装饰器目前处于Stage 2 Draft 中,一个功能在最终确定并成为语言的一部分之前要经历的总共 4 个阶段。它们可能会在不久的将来集成到该语言中,但其功能和细节可能会发生变化。因此,您必须使用 Babel 等转译器通过安装 transform-decorators Babel 插件将装饰器转换为 Node 运行时可以理解的代码(ECMAScript 2016)。

至于创建装饰器,您已经这样做了。每个装饰器只是一个包装另一个的函数,它提供了基于用例的参数,在您的情况下为targetkeydescriptor。你的logger 函数:

function logger(target, key, descriptor) 
  console.log("Cat snarling...");
  return descriptor;

已经是一名装饰师了。对于类属性和方法target 指的是属性的类,key 是属性名称,descriptor 是属性的描述符。然后调用装饰器并通过Object.defineProperty 定义类的属性,一旦去糖。您的示例可以归结为:

class Cat  

let meowDescriptor = 
  type: 'method',
  initializer: () => () => 
    console.log(' Meeeoow! ');
  ,
  enumerable: false,
  configurable: true,
  writable: true


function logger(target, key, descriptor) 
  console.log("Cat snarling...");
  return descriptor;


meowDescriptor = logger(Cat.prototype, 'meow', meowDescriptor);
Object.defineProperty(Cat.prototype, 'meow', 
  ...meowDescriptor,
  value: meowDescriptor.initializer()
);

对于类本身,装饰器采用一个参数,target,它描述了被装饰的类。我建议阅读some documentation 以熟悉该主题。

【讨论】:

三年后,它仍处于第 2 阶段草稿 :( 我正在编写 Node 服务 - 我认为在这里我会很安全,不需要使用转译器。

以上是关于如何使用和应用 JavaScript 装饰器?的主要内容,如果未能解决你的问题,请参考以下文章

我今天如何使用装饰器?

装饰器何时以及如何应用到 @angular 包中的装饰类

如何在vue.js 2应用程序中全局使用自定义装饰器?

如何在 React Redux 应用程序中使用装饰器?

如何将装饰器应用于超类的方法?

如何在子类上应用模式装饰器