【问题标题】:Is it possible to make constructor static in TypeScript?是否可以在 TypeScript 中将构造函数设为静态?
【发布时间】:2018-09-10 09:15:50
【问题描述】:

我在 TypeScript 中读到了一个静态构造函数并自己尝试过,但它不起作用。我想通过它来初始化一个静态变量(该方法只能调用一次)但我得到以下编译器错误:

错误:“静态”修饰符不能出现在构造函数声明中。

代码:

export class DataManagement {
  private static subjects: string[];

  static constructor() {
    DataManagement.subjects = [];
    //some more code here
  }
}

【问题讨论】:

  • 为什么不在类级别初始化subjects 字段,例如:private static subjects: string[] = []?为什么要在每次构造函数调用时重新初始化它?
  • 好的,谢谢!它确实有效!所以这是废话? github.com/Microsoft/TypeScript/issues/265
  • @BalázsÉdes 因为这只是一个例子——当然里面还有很多其他代码......但是没有必要分享代码......而且我不想在每次构造函数调用时初始化它,但只初始化一次 - 因为是 static 构造函数。就像 Java 中的静态初始化块。

标签: javascript typescript constructor static initialization


【解决方案1】:

您可以使用 .ts 文件中的静态代码来模拟静态构造函数。

假设你有一个类,它的目的是解析参数并将它们与一些默认值合并。

在你的类声明之后添加调用。

这是一个例子:

export class Env {
    private static _args: {}
    static get args() {
        return this._args;
    }

    static _Initialize() {
        // load settings from Environment
        process.argv.forEach(s => console.log(s))
        this._args =  Object.assign({}, defaults, this.parseCmdLine())
    }
}
Env._Initialize();

示例 TS 应用程序:https://github.com/v-andrew/ts-template

它与静态构造函数完全一样,需要注意的是:

  • 可以多次调用
  • 可以被Env的其他用户调用

为了消除这些问题,在_Initialize 末尾重新定义_Initialize:

        this._Initialize = ()=>{}

【讨论】:

    【解决方案2】:

    Symbol() 可用于此目的,但公共访问受限。

    const STATIC_INIT = Symbol(); // gives you a unique identifier
    
    class MyClass {
      public static[STATIC_INIT] = () => {
        // Your static init code here
      }
    }
    
    // Call the init once
    MyClass[STATIC_INIT]();
    

    【讨论】:

      【解决方案3】:

      虽然 C# 等其他语言确实具有静态构造函数,但 TypeScript(和 JavaScript)没有此功能。也就是说,您仍然可以静态定义一个您自己调用的函数。首先,让我先解释一下在哪些情况下您可能需要静态构造函数,然后再介绍您拥有的选项。

      何时使用静态构造函数

      静态构造函数在需要计算静态属性值的情况下很有用。如果您只想设置一个属性(为已知值),则不需要静态构造函数。可以这样做:

      class Example {
          public static info = 123;
          // ...
      }
      

      如果您需要计算该值,您可以通过三种方式“模拟”静态构造函数。我浏览了以下选项并在每个示例中设置了静态属性“info”。

      选项一:类声明后调用初始化函数

      在下面的代码中,函数_initialize 在类中静态定义,并在类声明后立即调用。在函数内部,this 指的是类,这意味着该关键字可用于设置任何静态值(如以下示例中的 info)。请注意,不能将函数设为私有,因为它是从外部调用的。

      class Example {
          public static info: number;
      
          public static _initialize() {
              // ...
              this.info = 123;
          }
      }
      Example._initialize();
      

      方案二:直接调用类内部的函数

      第二种选择是使用一个函数,它在类中创建后直接调用。该函数看起来只是类的一部分,但与类本身没有任何关系(除了在其内部定义),这意味着您不能在函数内部使用this

      class Example {
          static info: number;
      
          private static _initialize = (() => {
              // "this" cannot be used here
              Example.info = 1234;
          })();
      }
      

      备选方案:计算单个属性

      基于与选项2相同的思路,可以通过返回值来计算单个属性。如果您只想计算类的一个属性,这可能会很方便。

      class Example {
          public static info = (() => {
              // ... calculate the value and return it
              return 123;
          })();
      }
      

      使用什么

      如果您只想计算单个静态属性,您可能需要使用最后一种 (alternative) 方法。如果您需要进行更复杂的计算或想要设置更多属性,如果您不介意函数公开,我建议使用选项 1。否则,请使用选项 2。

      请注意,TypeScript 存储库中有一个 issue,其中包含有关选项 1 和 2 的更多讨论。

      【讨论】:

        【解决方案4】:

        所以使用静态构造函数有点用词不当。您不是尝试使构造函数方法静态,而是尝试创建静态实例化方法。它可以任意命名。我个人用过初始化。

        你可以让你的构造方法基本上是空白的

        constructor() {}

        然后有一个静态的初始化方法

        static initialize(): <type-to-use> { //initialization logic };

        通常在初始化方法中,您要使用关键字 new 调用构造函数,然后默认您的属性。

        【讨论】:

          【解决方案5】:

          你正在寻找一个对象:):

           const dataManagement: { subjects: string[] } = {
             subjects: []
           };
          
           export { dataManagement };
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-02-15
            • 1970-01-01
            • 2011-02-24
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多