在JavaScript构造函数中,接受和处理不同选项的最优雅方法是什么?

发布于 2025-02-13 09:25:01 字数 1154 浏览 1 评论 0原文

我正在尝试编写一个可以接受多个选项的JavaScript类构造函数(就像某些命令行工具一样,例如OpenSSL)。例如:

class myClass {
  constructor(pathOrSize, isPublic) {
    // Receive an file path
    if (typeof pathOrSize === 'string') {
      if (isPublic) {
        // Read public key file
        this.public = ...
      } else {
        // Read private key file, and then generate public key instance
        this.private = ...
        this.public = ...
      }
    } else if (typeof pathOrSize === 'number') {
      // Create a new key pair based on the given size
      this.private = ...
      this.public = ...
    } else {
      // Throw an error
    }
  }

  // Use this.public (or this.private, if provided) to encrypt/decrypt message
}

当实例化类时,this.public是必需的,但是this.private是可选的。条件逻辑可以保证,如果this.public未提供错误,将会丢弃错误。

对于第一个参数Pathorsize,有两种可能的输入类型,因此我在此处使用IF-ELSE检查该类型。然后,如果是字符串,基于iSpublic的值,我们将获得需要处理的另外两个不同的方案。就我而言,还有更多选项,使上面的代码段看起来更糟。它有效,但是冗长且难以阅读:(

鉴于JavaScript不支持过载(例如Java)和图案匹配(如Rust),是处理这样的情况的最优雅或有效的方法<是什么< /strong>

I'm trying to write a JavaScript class constructor that can accept multiple options (just like some command-line tools, e.g. OpenSSL). For example:

class myClass {
  constructor(pathOrSize, isPublic) {
    // Receive an file path
    if (typeof pathOrSize === 'string') {
      if (isPublic) {
        // Read public key file
        this.public = ...
      } else {
        // Read private key file, and then generate public key instance
        this.private = ...
        this.public = ...
      }
    } else if (typeof pathOrSize === 'number') {
      // Create a new key pair based on the given size
      this.private = ...
      this.public = ...
    } else {
      // Throw an error
    }
  }

  // Use this.public (or this.private, if provided) to encrypt/decrypt message
}

When the class is instantiated, this.public is required, but this.private is optional. The conditional logic guarantees that if this.public is not provided, an error will be thrown.

For the first parameter pathOrSize, there are two possible input types so I use an if-else here to check the type. Then if it's string, based on the value of isPublic, we will get two more different scenarios that need to be handled. In my case, there are more options, which make the code snippet above looks even worse. It works, but it's verbose and hard to read :(

Given the fact that JavaScript doesn't support overloading (like Java) and pattern matching (like Rust), what's the most elegant or efficient way to handle situations like this?

Thanks for any solutions or thoughts!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

懷念過去 2025-02-20 09:25:02

区分参数的典型方法是提供一个替代的静态函数来创建实例。这就是某些本地课程的完成方式。例如,array具有array.ofarray.fromobject code> object.fromentries ,object.create,...

如果我们遵循该模式,则您的示例代码可能会变为:

class MyClass {
  static fromFile(path, isPublic=true) {
    // read key file
    const content = ...
    // Pass the appropriate arguments to constructor
    return isPublic ? new this(null, content) : new this(content);
  }

  static fromSize(size) {
    // Create new key pairs based on the given size
    const privateKey = ...
    const publicKey = ...
    return new this(privateKey, publicKey);
  }

  // Constructor is dumb: it has little logic
  constructor(privateKey, publicKey) {
    // If no public key is given, produce it from the private key
    if (publicKey === undefined) {
        if (privateKey === undefined) throw Error("must provide at least one key");
        // Generate public key instance from private key
        publicKey = ...
    }
    this.privateKey = privateKey ?? null; // turn undefined into null
    this.publicKey = publicKey;
  }
}

// Example calls:
let x = MyClass.fromFile("/testPublic.key");
let y = MyClass.fromSize(5);
let z = new MyClass("a", "b");

A typical way to differentiate between parameters, is to provide an alternative, static function to create an instance. This is how it is done for some native classes. For instance, Array has Array.of, Array.from, and Object has Object.fromEntries, Object.create, ...

If we follow that pattern, your example code could become:

class MyClass {
  static fromFile(path, isPublic=true) {
    // read key file
    const content = ...
    // Pass the appropriate arguments to constructor
    return isPublic ? new this(null, content) : new this(content);
  }

  static fromSize(size) {
    // Create new key pairs based on the given size
    const privateKey = ...
    const publicKey = ...
    return new this(privateKey, publicKey);
  }

  // Constructor is dumb: it has little logic
  constructor(privateKey, publicKey) {
    // If no public key is given, produce it from the private key
    if (publicKey === undefined) {
        if (privateKey === undefined) throw Error("must provide at least one key");
        // Generate public key instance from private key
        publicKey = ...
    }
    this.privateKey = privateKey ?? null; // turn undefined into null
    this.publicKey = publicKey;
  }
}

// Example calls:
let x = MyClass.fromFile("/testPublic.key");
let y = MyClass.fromSize(5);
let z = new MyClass("a", "b");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文