web-dev-qa-db-ja.com

複数のコンストラクターのJavaScriptパターン

インスタンスには異なるコンストラクターが必要です。その一般的なパターンは何ですか?

90
codeholic

これはどうやって見つけますか?

function Foobar(foobar) {
    this.foobar = foobar;
}

Foobar.prototype = {
    foobar: null
};

Foobar.fromComponents = function(foo, bar) {
    var foobar = foo + bar;
    return new this(foobar);
};
27
codeholic

JavaScriptには、メソッドやコンストラクターを含む関数のオーバーロードがありません。

関数に渡すパラメーターの数とタイプに応じて関数の動作を変えたい場合は、手動でスニッフィングする必要があります。 JavaScriptは、宣言された引数の数よりも多いか少ない引数で関数を呼び出します。

function foo(a, b) {
    if (b===undefined) // parameter was omitted in call
        b= 'some default value';

    if (typeof(a)==='string')
        this._constructInSomeWay(a, b);
    else if (a instanceof MyType)
        this._constructInSomeOtherWay(a, b);
}

argumentsに配列のようにアクセスして、さらに引数を渡すこともできます。

より複雑な引数が必要な場合は、それらの一部またはすべてをオブジェクトルックアップ内に配置することをお勧めします。

function bar(argmap) {
    if ('optionalparam' in argmap)
        this._constructInSomeWay(argmap.param, argmap.optionalparam);
    ...
}

bar({param: 1, optionalparam: 2})

Pythonは、関数のオーバーロードよりも実用的で優雅な方法で、ほとんどのユースケースをカバーするためにデフォルト引数と名前付き引数を使用する方法を示しています。 JavaScript、それほどではありません。

106
bobince

Bobinceの答えのように手でやる気がなかったので、jQueryのプラグインオプションパターンを完全に取り除いただけです。

コンストラクタは次のとおりです。

//default constructor for Preset 'class'
function Preset(params) {
    var properties = $.extend({
        //these are the defaults
        id: null,
        name: null,
        inItems: [],
        outItems: [],
    }, params);

    console.log('Preset instantiated');
    this.id = properties.id;
    this.name = properties.name;
    this.inItems = properties.inItems;
    this.outItems = properties.outItems;
}

インスタンス化のさまざまな方法を次に示します。

presetNoParams = new Preset(); 
presetEmptyParams = new Preset({});
presetSomeParams = new Preset({id: 666, inItems:['item_1', 'item_2']});
presetAllParams = new Preset({id: 666, name: 'SOpreset', inItems: ['item_1', 'item_2'], outItems: ['item_3', 'item_4']});

そして、それがそれを作ったものです:

presetNoParams
Preset {id: null, name: null, inItems: Array[0], outItems: Array[0]}

presetEmptyParams
Preset {id: null, name: null, inItems: Array[0], outItems: Array[0]}

presetSomeParams
Preset {id: 666, name: null, inItems: Array[2], outItems: Array[0]}

presetAllParams
Preset {id: 666, name: "SOpreset", inItems: Array[2], outItems: Array[2]}
12
Jacob McKay

Eruciformの答えをさらに進めると、new呼び出しをinitメソッドにチェーンできます。

function Foo () {
    this.bar = 'baz';
}

Foo.prototype.init_1 = function (bar) {
    this.bar = bar;
    return this;
};

Foo.prototype.init_2 = function (baz) {
    this.bar = 'something to do with '+baz;
    return this;
};

var a = new Foo().init_1('constructor 1');
var b = new Foo().init_2('constructor 2');
9
laughingbovine

複数のコンストラクターには、パラメーターのデフォルト値で十分な場合があります。そして、それで十分でない場合は、コンストラクター機能のほとんどを、後で呼び出されるinit(other-params)関数にラップしようとします。ファクトリコンセプトを使用して、必要な他のオブジェクトを効果的に作成できるオブジェクトを作成することも検討してください。

http://en.wikipedia.org/w/index.php?title=Factory_method_pattern&oldid=363482142#Javascript

3
eruciform

これは、 JavaScriptとCSS3を使用したHTML5でのプログラミング-Exam Ref の複数のコンストラクターの例です。

function Book() {
    //just creates an empty book.
}


function Book(title, length, author) {
    this.title = title;
    this.Length = length;
    this.author = author;
}

Book.prototype = {
    ISBN: "",
    Length: -1,
    genre: "",
    covering: "",
    author: "",
    currentPage: 0,
    title: "",

    flipTo: function FlipToAPage(pNum) {
        this.currentPage = pNum;
    },

    turnPageForward: function turnForward() {
        this.flipTo(this.currentPage++);
    },

    turnPageBackward: function turnBackward() {
        this.flipTo(this.currentPage--);
    }
};

var books = new Array(new Book(), new Book("First Edition", 350, "Random"));
1
Simon Stanford

前に述べたように、複数のソリューション、日付などの一般的なものは静的メソッドです:

Date.UTC("some params"); 

これは適切なコンストラクタではありませんが、これは

function someObject(a,b,c,d,e,f) {
 a = a || "default";
 b = b || "defaultb"
}

TypeScriptを使用するか、es5に変換できますか?

constructor(a:string, b = "default value", c:number? //optional
) {

}
1
Mathijs Segers

クラスのインスタンスを返す静的メソッドでクラスを使用できます

    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)
        }
        static BAndDInstance(b,d){
            return new MyClass(null,b, null,d)
        }
    }

    //new Instance just with a and other is nul this can
    //use for other params that are first in constructor
    const myclass=new MyClass(a)

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

    //another example for b and d
    const BAndD=MyClass.BAndDInstance(b,d)

このパターンを使用すると、マルチコンストラクターを作成できます

0
mahdi shahbazi