2010-07-10 16 views

Respuesta

22

¿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); 
}; 
+2

devuelve nuevo esto (foobar); no funciona Cambio al devolver el nuevo Foobar (foobar); y todo es trabajo correcto. – isxaker

+6

No lo entiendo ¿Puedes agregar el código donde realmente lo estás usando? ¿Vas a tener que llamar desde Componentes cada vez? Porque eso no es realmente un constructor, sino una función de ayuda. La respuesta de @ bobince parece más precisa entonces. – hofnarwillie

+1

Si esto * does * funciona, es un patrón complicado. –

3

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

+1

El método de fábrica parece una buena solución, solo asegúrese de no confundirlo con el uso de una clase de fábrica separada, que probablemente sea completamente irrelevante en este caso de uso. –

+1

Ese enlace no va a ninguna parte. No hay un ancla de Javascript en esa página. – Rob

+1

apuntando a la versión anterior. wiki eliminado js ejemplos. – eruciform

88

JavaScript no tiene la sobrecarga de funciones, incluyendo 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á olfatearlas 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 puede acceder a arguments como una matriz similar a conseguir ningún otro argumento se ha pasado.

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

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

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

Python demuestra cómo defecto y argumentos con nombre pueden ser utilizados para cubrir la mayoría de los casos de uso de un modo más práctico y elegante que la sobrecarga de funciones. JavaScript, no tanto.

+1

Gracias, esto es realmente bueno. Diría que la segunda opción es útil no solo cuando tienes argumentos complejos, sino también argumentos simples pero difíciles de distinguir, p. Ej. compatible con 'MyObj ({foo:" foo "})' más 'MyObj ({barra:" barra "})'. MyObj tiene dos constructores, pero ambos toman un argumento, que es una cadena :-) –

+1

Puedes agregar más al código de ejemplo para este ejemplo en particular. –

+0

Hola @DougHauf, el libro de Crockford 'JavaScript: The Good Parts' tiene una sección sobre este nombre 'Object Specifiers', muchos ejemplos se refieren a él en línea. –

9

Yendo más lejos con la respuesta de eruciform, se pueden encadenar su llamada new en su método 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'); 
+0

Entonces, básicamente, lo que está haciendo aquí es tomar el objeto Foo y luego llamar a los parámetros init_1 e init_2 con las funciones del prototipo. Si init_1 e init_2 tienen la palabra función con ellos. –

+0

tiene que haber un punto y coma después de} en el primer Foo(). –

+0

Gracias Doug, hice el cambio. – laughingbovine

10

no tenía ganas de hacerlo a mano como en la respuesta de bobince, por lo que sólo hubieran estafado patrón de opciones del plugin 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; 
} 

He aquí 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]} 
+0

He rodado el mismo patrón en node.js también ahora con: https://www.npmjs.com/package/extend –

1

Así que sí lo expresado antes, varias soluciones, lo que ves en general en cosas como la fecha son los métodos estáticos:

Date.UTC("some params"); 

Esto no es un constructor adecuado, sin embargo, esto es a pesar de

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

puede ir a máquina o transpile a ES5?

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

} 
2

Este es el ejemplo dado para varios constructores en Programming in HTML5 with JavaScript and CSS3 - 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")); 
+0

¿Y la inmutabilidad? usar el prototipo pone las propiedades públicas, ¿verdad? –

Cuestiones relacionadas