Pregunta Patrón de JavaScript para múltiples constructores


Necesito diferentes constructores para mis instancias. ¿Cuál es un patrón común para eso?


74
2017-07-10 20:23


origen


Respuestas:


JavaScript no tiene una función de sobrecarga, incluidos los métodos o constructores.

Si desea que una función se comporte de manera diferente según el número y los tipos de parámetros que le pase, deberá olfatearlos manualmente. JavaScript gustará llamar a una función con más o menos que el número declarado de argumentos.

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);
}

También puedes acceder arguments como una matriz para obtener cualquier otro argumento pasado.

Si necesita argumentos más complejos, puede ser una buena idea colocar algunos o todos dentro de una búsqueda de objetos:

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

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

Python demuestra cómo los argumentos predeterminados y nombrados se pueden usar para cubrir la mayoría de los casos de uso de una manera más práctica y elegante que la sobrecarga de funciones. JavaScript, no tanto.


92
2017-07-10 21:29



¿Cómo encuentras este?

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

Foobar.prototype = {
    foobar: null
};

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

24
2017-07-12 20:16



No tenía ganas de hacerlo a mano como en la respuesta de Bobince, así que simplemente arranqué por completo el patrón de opciones del complemento de jQuery.

Aquí está el constructor:

//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;
}

Aquí hay diferentes formas de creación de instancias:

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']});

Y esto es lo que hizo:

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]}

11
2017-10-05 03:09



Yendo más allá con la respuesta de eruciform, puedes encadenar tu new llama a tu init método.

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
2017-11-30 17:54



A veces, los valores predeterminados para los parámetros son suficientes para múltiples constructores. Y cuando eso no es suficiente, intento envolver la mayoría de las funciones del constructor en una función init (other-params) que se llama después. También considere utilizar el concepto de fábrica para crear un objeto que pueda crear efectivamente los otros objetos que desee.

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


3
2017-07-10 20:32



Este es el ejemplo dado para múltiples constructores en Programación en HTML5 con JavaScript y CSS3 - Referencia de examen.

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"));

2
2018-05-02 20:21



Así que sí, como se expresó anteriormente, con múltiples soluciones, lo que se ve en general en cosas como la fecha son los métodos estáticos:

Date.UTC("some params"); 

Aunque este no es un constructor apropiado, esto es

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

¿Puede ir mecanografiado o transpilelo a es5?

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

}

1
2017-07-29 12:57