你能在 es6 及更高版本中创建多个构造函数吗?

Can you make multiple constructors in es6 and up?

问题

所以基本上我正在尝试使用多个构造函数制作一个 class 以便它更加用户友好。但是当我 运行 代码输出时:

SyntaxError: /FileSystem.js: Duplicate constructor in the same class (13:2)

我知道 可以回答这个问题,但我的代码对每个构造函数都有不同的参数:

Va运行 Sukheja 的代码

    function Book() {
        //just creates an empty book.
    }
    
    
    function Book(title, length, author) {
        this.title = title;
        this.Length = length;
        this.author = author;
    }

我的代码

    class File
        constructor(Name, Type, Data) {
            this.Name = Name
            this.Type = Type
            this.Data = Data
      }
        constructor(FileName, Data) {
        let FileNameSplit = FileName.split('.').pop(); 
        this.Type = FileNameSplit[FileNameSplit.length - 1];
        
        let NameSplit = FileNameSplit.pop()
        this.Name = FileName;
        
        this.Data = Data
      }
    }

如您所见,我的代码有 2 个构造函数(一个带有 constructor(Name, Type, Data) {,另一个带有 constructor(FileName, Data) {)。所以你可以看到使用 Saransh Kataria 的代码是行不通的。 .

Saransh Kataria 的代码

    constructor(title, length, author) {
        if(!arguments.length) {
            // empty book
        }
        else {
            this.title = title;
            this.Length = length;
            this.author = author;
        }
   }

额外信息

IDE: Codesandbox

浏览器: Chrome

完整代码:

    class File {
      /**
       * 
       * @param {String} Name Name Of File
       * @param {(String|Number)} Type File Type / Exstention
       * @param {Array} Data 
       */
        constructor(Name, Type, Data) {
            this.Name = Name
            this.Type = Type
            this.Data = Data
      }
        constructor(FileName, Data) {
        let FileNameSplit = FileName.split('.').pop(); 
        this.Type = FileNameSplit[FileNameSplit.length - 1];
        
        let NameSplit = FileNameSplit.pop()
        this.Name = FileName;
        
        this.Data = Data
      }
    }

    let Blob1 = new Blob([""])

    console.log(Blob1)

Javascript 不支持定义多个构造函数。看起来你只是想做函数重载。

在Javascript中,你不会这样做。相反,您使用您期望的最大参数数量声明版本,并动态测试 OP 传递的内容,并根据传递或未传递的内容调整您的行为。

您可以在 Javascript 此处查看函数重载的一般说明:

How to overload functions in javascript?

如果构造函数的版本差异很大,那么您可以将其更改为仅采用一个对象,然后在调用函数之前将所需的属性分配给该对象。然后您的代码将询问对象并查看传递的内容并相应地调整其行为。

例如,要同时支持这两个:

class File {
    constructor(Name, Type, Data) {
        this.Name = Name
        this.Type = Type
        this.Data = Data
  }
    constructor(FileName, Data) {
    let FileNameSplit = FileName.split('.').pop(); 
    this.Type = FileNameSplit[FileNameSplit.length - 1];
    
    let NameSplit = FileNameSplit.pop()
    this.Name = FileName;
    
    this.Data = Data
  }
}

您可以通过多种方式执行此类操作。最简单的是,如果所需参数的类型不同,而我们不确切知道这些参数是什么类型。在不知道这些类型的情况下,我可能只是传入一个具有命名属性的对象:

class File
    constructor(options) {
       if (options.Name && options.Type) {
           this.Name = options.Name
           this.Type = options.Type
           this.Data = options.Data
       } else if (options.FileName && options.Data) {
           let FileNameSplit = options.FileName.split('.').pop(); 
           this.Type = FileNameSplit[FileNameSplit.length - 1];
    
           let NameSplit = FileNameSplit.pop()
           this.Name = options.FileName;
    
           this.Data = options.Data
       } else {
           throw new Error("improper arguments to File constructor);
       }
    }
}

仅供参考,Javascript 中的习惯是 属性 名称和参数名称以及常规变量名称以小写字母开头(我在代码中保留了您已有的名称)。 Class 名称通常大写。


因为您知道 Data 参数是唯一的数组参数,您可以像这样动态检测传递了哪些参数:

class File {
    // args can be in either of these forms:
    // (Name, Type, Data)
    // (FileName, Data)
    constructor(Name, Type, Data) {
        if (Array.isArray(Data)) {
            // args must be (Name, Type, Data)
            this.Name = Name
            this.Type = Type
            this.Data = Data
        } else if (Array.isArray(Type)) {
            // args must be (FileName, Data)
            const FileName = Name;
            this.Name = FileName;
            this.Data = Type;
            let FileNameSplit = FileName.split('.').pop(); 
            this.Type = FileNameSplit[FileNameSplit.length - 1];
        } else {
            throw new TypeError("unexpected or missing arguments to File constructor")
        }
    }
}