为什么 JavaScript ES6 不支持多构造函数类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32626524/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 13:58:40  来源:igfitidea点击:

Why doesn't JavaScript ES6 support multi-constructor classes?

javascriptclassconstructorecmascript-6

提问by Manhhailua

I want to write my Javascript class like below.

我想像下面这样编写我的 Javascript 类。

class Option {
    constructor() {
        this.autoLoad = false;
    }

    constructor(key, value) {
        this[key] = value;
    }

    constructor(key, value, autoLoad) {
        this[key] = value;
        this.autoLoad = autoLoad || false;
    }
}

I think it would be nice if we can write out class in this way. Expect to happen:

我想如果我们能这样写出类就好了。预计会发生:

var option1 = new Option(); // option1 = {autoLoad: false}
var option2 = new Option('foo', 'bar',); // option2 = {foo: 'bar'}
var option3 = new Option('foo', 'bar', false); // option3 = {foo: 'bar', autoLoad: false}

采纳答案by CodingIntrigue

I want to write my Javascript class like below

我想像下面这样编写我的 Javascript 类

You can't, in the same way you can't overload standard functions like that. What you cando is use the argumentsobject to query the number of arguments passed:

你不能,就像你不能重载这样的标准函数一样。您可以做的是使用参数对象来查询传递的参数数量:

class Option {
    constructor(key, value, autoLoad) {
        // new Option()
        if(!arguments.length) {
            this.autoLoad = false;
        }
        // new Option(a, [b, [c]])
        else {
            this[key] = value;
            this.autoLoad = autoLoad || false;
        }
    }
}

Babel REPL Example

Babel REPL 示例

Of course (with your updated example), you could take the approach that you don't care about the number of arguments, rather whether each individual value was passed, in which case you could so something like:

当然(使用您更新的示例),您可以采用不关心参数数量的方法,而不必关心是否传递了每个单独的值,在这种情况下,您可以这样做:

class Option {
    constructor(key, value, autoLoad) {
        if(!key) { // Could change this to a strict undefined check
            this.autoLoad = false;
            return;
        }
        this[key] = value;
        this.autoLoad = autoLoad || false;
    }
}

回答by Bardi Harborow

What you want is called constructor overloading. This, and the more general case of function overloading, is not supported in ECMAScript.

你想要的是构造函数重载。ECMAScript 不支持这种情况以及更一般的函数重载情况。

ECMAScript does not handle missing arguments in the same way as more strict languages. The value of missing arguments is left as undefinedinstead of raising a error. In this paradigm, it is difficult/impossible to detect which overloaded function you are aiming for.

ECMAScript 不像更严格的语言那样处理丢失的参数。缺少参数的值保留为undefined而不是引发错误。在这种范式中,很难/不可能检测到您的目标是哪个重载函数。

The idiomatic solution is to have one function and have it handle all the combinations of arguments that you need. For the original example, you can just test for the presence of keyand valuelike this:

惯用的解决方案是拥有一个函数并让它处理您需要的所有参数组合。对于原始示例,您可以测试是否存在keyvalue像这样:

class Option {
  constructor(key, value, autoLoad = false) {
    if (typeof key !== 'undefined') {
      this[key] = value;
    }
    this.autoLoad = autoLoad;
  }
}

回答by GFoley83

Another option would be to allow your constructor to take an object that is bound to your class properties:

另一种选择是允许您的构造函数采用绑定到您的类属性的对象:

class Option {
  // Assign default values in the constructor object 
  constructor({key = 'foo', value, autoLoad = true} = {}) {
      this.key = key;
      // Or on the property with default (not recommended)
      this.value = value || 'bar';
      this.autoLoad = autoLoad;
      
      console.log('Result:', this);
  }
}

var option1 = new Option();
// Logs: {key: "foo", value: "bar", autoLoad: true}

var option2 = new Option({value: 'hello'});
// Logs: {key: "foo", value: "hello", autoLoad: true}

This is even more useful with Typescript as you can ensure type safety with the values passed in (i.e. keycould only be a string, autoLoada boolean etc).

这对于 Typescript 更有用,因为您可以通过传入的值确保类型安全(即key只能是字符串、autoLoad布尔值等)。

回答by Diogo Eichert

Guessing from your sample code, all you need is to use default values for your parameters:

从您的示例代码中猜测,您只需要为参数使用默认值:

class Option {
    constructor(key = 'foo', value = 'bar', autoLoad = false) {
        this[key] = value;
        this.autoLoad = autoLoad;
    }
}

Having said that, another alternative to constructor overloading is to use static factories. Suppose you would like to be able to instantiate an object from plain parameters, from a hash containing those same parameters or even from a JSON string:

话虽如此,构造函数重载的另一种替代方法是使用静态工厂。假设您希望能够从普通参数、包含这些相同参数的散列或什至从 JSON 字符串实例化一个对象:

class Thing {
    constructor(a, b) {
        this.a = a;
        this.b = b;
    }

    static fromHash(hash) {
        return new this(hash.a, hash.b);
    }

    static fromJson(string) {
        return this.fromHash(JSON.parse(string));
    }
}

let thing = new Thing(1, 2);
// ...
thing = Thing.fromHash({a: 1, b: 2});
// ...
thing = Thing.fromJson('{"a": 1, "b": 2}');

回答by Diogo Eichert

Here's a hack for overloading based on arity (number of arguments). The idea is to create a function from a number of functions with different arities (determined by looking at fn.length).

这是一个基于 arity(参数数量)的重载技巧。这个想法是从多个具有不同元数的函数(通过查看 确定fn.length)创建一个函数。

function overloaded(...inputs) {
  var fns = [];

  inputs.forEach(f => fns[f.length] = f);

  return function() {
    return fns[arguments.length].apply(this, arguments);
  };
}

var F = overloaded(
  function(a)    { console.log("function with one argument"); },
  function(a, b) { console.log("function with two arguments"); }
);

F(1);
F(2, 3);

Of course this needs a lot of bullet-proofing and cleaning up, but you get the idea. However, I don't think you'll have much luck applying this to ES6 class constructors, because they are a horse of a different color.

当然,这需要大量的防弹和清理工作,但您懂的。但是,我认为将其应用于 ES6 类构造函数不会有太大的运气,因为它们是不同颜色的马。

回答by mahdi shahbazi

you can use static methods,look at my answer to same question

你可以使用静态方法,看看我对同一个问题的回答

class MyClass {
    constructor(a,b,c,d){
        this.a = a
        this.b = b
        this.c = c
        this.d = d
    }
    static BAndCInstance(b,c){
        return new MyClass(null,b,c)
    }
}

//a Instance that has b and c params
MyClass.BAndCInstance(b,c)

回答by Azat

Use object.assignewith arguments with this

object.assigne与参数一起使用

This={...this,...arguments}