首页  >  文章  >  web前端  >  JavaScript 装饰器和自动访问器

JavaScript 装饰器和自动访问器

王林
王林原创
2024-07-17 12:50:36944浏览

JavaScript Decorators and Auto-Accessors

如何创建 JavaScript 装饰器以及如何使用自动访问器帮助改善开发者体验的演练。

目录

  • 上下文和规范
  • 前言
  • 自动访问器
  • 创建装饰器
    • 简单的装饰器
    • 使用装饰器进行验证
    • 装饰器选项
  • 元数据

背景和规范

GitHub 上的装饰器提案已经在分解装饰器的基本用例方面做得很好。我的目标不是在那里重新创建这些示例,而是突出一些鲜为人知的功能和交互。此外,在本系列的下一篇文章中,我将重点介绍如何在单个类属性上组合或链接多个装饰器。

前言

每个代码示例都将附带一个交互式 Babel REPL 游乐场的链接,因此您可以自己尝试,而无需设置 polyfill 或启动存储库。在我的所有示例中,应选中左上角(“设置”下)的“评估”选项,这意味着您将能够查看代码、编辑它、打开浏览器的开发控制台,并在那里查看日志/结果。

你不需要关注 Babel REPL 右侧的转译代码,除非你想深入研究装饰器的 polyfill。 Babel REPL 的左侧是您可以编辑和编写代码来亲自尝试的地方。

要强调的是,您的开发人员工具的控制台应该显示控制台日志。如果没有,请确保在左上角选中“评估”。

自动存取器

装饰器规范的一个重要功能是自动访问器。我们将从学习它们是什么以及使用自动访问器如何使编写装饰器变得更容易开始。

装饰者提案在这里概述了自动访问器。但最终它只是一个简单的功能;让我们看一个基本的工作示例:Babel REPL。

class MyClass {
  accessor myBoolean = false
}

在此类定义中,访问器关键字位于属性名称之前。然而,这并没有真正改变属性的任何内容 - 接下来,我们将看到自动访问器与装饰器结合使用时有多么有用。

(请注意,您还可以将 static 与自动访问器一起使用,例如静态访问器 myBoolean = false)

创建装饰器

为了更好地理解为什么我们使用自动访问器,让我们构建一些装饰器。

一个简单的装饰器

我们首先将自动访问器与实际上作用不大的装饰器结合起来,以便了解语法。

这是一个保留内部变量的函数装饰器,并允许您通过类上的属性获取和设置该变量:Babel REPL

function simpleDecorator(value, context) {
  let internalValue = false
  return {
    get() {
      return internalValue
    },
    set(val) {
      internalValue = val
      return internalValue
    }
  }
}

class MyClass {
  @simpleDecorator
  accessor myBoolean
}

这个装饰器返回一个具有两个方法的对象:get() 和 set()。这就是自动访问器的装饰器如何“装饰”或将属性的 setter 和 getter 包装在一个地方;我们不必创建 simpleGetterDecorator 和 simpleSetterDecorator。相反,我们使用自动访问器将它们组合成一个定义,这更容易。

最后,到目前为止,这看起来是一个相当正常的函数 - 这非常适合介绍!

使用装饰器进行验证

为了让我们为本文的其余部分做好准备,让我们更新我们的装饰器,以便它实际上进行某种验证。我们将制作一个装饰器,它只允许您设置偶数,而不允许设置其他数字。看起来像这样:Babel REPL

function onlyEvenNumbers(value, context) {
  let internalNumber = 0
  return {
    get() {
      return internalNumber
    },
    set(val) {
      const num = Number(val)
      if(isNaN(num)) {
        // don't set the value if it's not a number or coerced to a number
        return internalNumber
      }
      if(num % 2 !== 0) {
        // don't allow odd numbers
        return internalNumber
      }
      internalNumber = val
      return internalNumber
    }
  }
}

class MyClass {
  @onlyEvenNumbers
  accessor myEvenNumber
}

因此,我们向 set() 方法添加逻辑,现在任何尝试在我们的类上设置 myEvenNumber 属性的人都将通过该验证逻辑。不错。

装饰器选项

现在我们有了一个很好的仅偶数装饰器,让我们让它处理偶数和奇数,并提供一个选项来配置我们想要的数字类型!

幸运的是,因为这是我们在这里编写的看起来相当正常的 JavaScript,所以配置它以这种方式工作并不太难。我们用一个接受选项的函数包装原始装饰器,然后返回装饰器。 Babel REPL

function evensOrOdds(onlyEvens = true) {
  return function decorator(value, context) {
    let internalNumber = 0
    return {
      get() {
        return internalNumber
      },
      set(val) {
        const num = Number(val)
        if(isNaN(num)) {
            // don't set the value if it's not a number
            return internalNumber
        }
        if(num % 2 !== (onlyEvens ? 0 : 1)) {
            return internalNumber
        }
        internalNumber = val
        return internalNumber
      }
    }
  }
}

class MyClass {
  @evensOrOdds(true)
  accessor myEvenNumber

  @evensOrOdds(false)
  accessor myOddNumber
}

我们现在已经将装饰器配置为接受任意选项,这允许装饰器的用户自定义其行为。耶。

元数据

装饰器可以使用的另一个工具是 context.metadata。该对象被传递给每个装饰器,您可以将其用于各种用途,但您需要小心,因为元数据对象对于每个装饰器的所有调用都是相同的。

继续学习

继续阅读本系列的下一篇文章,了解如何将装饰器组合(或应用多个)到单个属性!

以上是JavaScript 装饰器和自动访问器的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn