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

前端 未结 8 2134
终归单人心
终归单人心 2020-12-03 04:25

I want to write my Javascript class like below.

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

    constructor(key, value) {
               


        
相关标签:
8条回答
  • 2020-12-03 04:38

    I want to write my Javascript class like below

    You can't, in the same way you can't overload standard functions like that. What you can do is use the arguments object 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

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-03 04:39

    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)
    
    0 讨论(0)
  • 2020-12-03 04:45

    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. key could only be a string, autoLoad a boolean etc).

    0 讨论(0)
  • 2020-12-03 04:51

    Its not the overload I wanted, but this is a basic version of how I faked my way through creating an obj1 with some different initialization behavior. I realize I could have expanded the arguments as stated above, but I already had a nasty set of arguments and relatively different data sources to deconstruct that would have really distorted my objectives; this just made it cleaner for my situation...

    class obj1{
      constructor(v1, v2){
        this.a = v1;
        this.b = v2;
      }
    }
    
    class obj1Alt{
      constructor(v1, v2){
        return new obj1(v1*2,v2*2);
      }
    }
    
    new obj1(2,4) // returns an obj1
    new obj1Alt(2,4) // also returns an obj1
    

    Disclaimer: I've been programming for a long time, but I am fairly new to JS; probably not a best practice.

    0 讨论(0)
  • 2020-12-03 05:00

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

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

    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 key and value like this:

    class Option {
      constructor(key, value, autoLoad = false) {
        if (typeof key !== 'undefined') {
          this[key] = value;
        }
        this.autoLoad = autoLoad;
      }
    }
    
    0 讨论(0)
  • 2020-12-03 05:04

    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).

    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.

    0 讨论(0)
提交回复
热议问题