web-dev-qa-db-ja.com

JavaScript ES6がマルチコンストラクタークラスをサポートしないのはなぜですか?

以下のようにJavascriptクラスを書きたいです。

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

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

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

この方法でクラスを書き出すことができればいいと思います。起こることを期待:

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}
44
Manhhailua

以下のようにJavascriptクラスを書きたい

同じような方法で、そのような標準関数をオーバーロードすることはできません。あなたがcanすることは arguments オブジェクトを使用して渡された引数の数を問い合わせることです:

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例

もちろん(更新された例では)、引数の数を気にしないアプローチではなく、個々の値が合格した場合、次のようなことができます:

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;
    }
}
29
CodingIntrigue

必要なものは、コンストラクターのオーバーロードと呼ばれます。これ、および 関数のオーバーロード のより一般的なケースは、ECMAScriptではサポートされていません。

ECMAScriptは、より厳密な言語と同じ方法で欠落している引数を処理しません。欠落している引数の値は、エラーを発生させる代わりにundefinedのままになります。このパラダイムでは、目的とするオーバーロード機能を検出することは困難/不可能です。

慣用的な解決策は、1つの関数を持ち、必要な引数のすべての組み合わせを処理することです。元の例では、次のようにkeyおよびvalueの存在をテストできます。

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

別のオプションは、コンストラクターがクラスプロパティにバインドされたオブジェクトを取得できるようにすることです。

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}

これは、渡された値でタイプセーフを保証できるため、TypeScriptでさらに便利です(つまり、keyは文字列のみ、autoLoadはブール値など)。

6
GFoley83

これは、アリティ(引数の数)に基づいてオーバーロードするためのハックです。考え方は、異なるアリティを持つ多数の関数から関数を作成することです(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);

もちろん、これには多くの防弾とクリーンアップが必要ですが、あなたはアイデアを得る。ただし、ES6クラスコンストラクターは異なる色の馬であるため、これをES6クラスコンストラクターに適用することはそれほど幸運ではないと思います。

6
user663031

サンプルコードから推測すると、必要なのは、パラメーターの既定値を使用することだけです。

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

そうは言っても、コンストラクターのオーバーロードに代わる別の方法は、静的ファクトリーを使用することです。単純なパラメーター、同じパラメーターを含むハッシュ、または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}');
3
Diogo Sperb

静的メソッドを使用して、 同じ質問に対する私の答え を見てください

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)
1
mahdi shahbazi