2010-07-10 19 views

risposta

22

Come si trova questo?

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

Foobar.prototype = { 
    foobar: null 
}; 

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

return new this (foobar); non funziona Cambio in cambio di nuovo Foobar (foobar); e tutto è lavoro corretto. – isxaker

+6

Non capisco. Puoi aggiungere il codice dove lo stai effettivamente usando? Dovrai chiamare daComponents ogni volta? Perché non è veramente un costruttore, ma piuttosto una funzione di aiuto. la risposta di @ bobince sembra più accurata di allora. – hofnarwillie

+1

Se questo * funziona *, è uno schema complicato. –

3

A volte, i valori predefiniti per i parametri sono sufficienti per più costruttori. E quando ciò non è sufficiente, cerco di racchiudere la maggior parte delle funzionalità del costruttore in una funzione init (other-params) chiamata in seguito. Considera anche l'utilizzo del concetto di fabbrica per creare un oggetto che possa effettivamente creare gli altri oggetti desiderati.

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

+1

Il metodo di produzione si presenta come una buona soluzione: assicurati di non confonderlo con l'uso di una classe factory separata, che probabilmente è completamente irrilevante in questo caso d'uso. –

+1

Questo collegamento non va da nessuna parte. Non ci sono ancora Javascript in quella pagina. – Rob

+1

indica la versione precedente. wiki rimosso esempi js. – eruciform

88

JavaScript non ha overloading di funzioni, tra cui per metodi o costruttori.

Se si desidera che una funzione si comporti in modo diverso a seconda del numero e dei tipi di parametri che si passano, è necessario annusarli manualmente. JavaScript chiamerà felicemente una funzione con più o meno del numero dichiarato di argomenti.

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

è anche possibile accedere arguments come una matrice simile per ottenere ulteriori argomenti passati.

Se avete bisogno di argomenti più complessi, può essere una buona idea di mettere alcuni o tutti al loro interno una ricerca oggetto:

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

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

Python dimostra come predefinita e argomenti con nome possono essere utilizzati per coprire il maggior numero di casi d'uso in modo più pratico e grazioso di overloading di funzioni. JavaScript, non così tanto.

+1

Grazie, è davvero carino. Direi che la seconda opzione è utile non solo quando si hanno argomenti complessi, ma anche argomenti semplici, ma difficili da distinguere, ad es. supportando 'MyObj ({foo:" foo "})' più 'MyObj ({bar:" bar "})'. MyObj ha due costruttori - ma entrambi accettano un argomento, che è una stringa :-) –

+1

Puoi aggiungere altro al codice di esempio per questo particolare esempio. –

+0

Hi @DougHauf, il libro di Crockford 'JavaScript: The Good Parts' ha una sezione su questo nome 'Object Specifier', molti esempi si riferiscono ad esso online. –

9

Andando avanti con la risposta di larva eruciforme, è possibile concatenare il vostro new chiamata nel metodo di 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

Quindi in pratica quello che stai facendo è prendere l'oggetto Foo e poi chiamare i parametri init_1 e init_2 con le funzioni del prototipo. Se init_1 e init_2 hanno la parola funzione con loro. –

+0

deve esserci un punto e virgola dopo il} nel primo Foo(). –

+0

Grazie Doug, ho apportato la modifica. – laughingbovine

10

non avevo voglia di farlo a mano come nella risposta di bobince, quindi ho solo completamente derubati modello Opzioni del plugin di jQuery.

Ecco il costruttore:

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

Ecco diversi modi di esemplificazione:

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

Ed ecco che cosa ha fatto:

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

Ho arrotolato lo stesso modello anche in node.js con: https://www.npmjs.com/package/extend –

1

Quindi sì come formulata prima, più soluzioni, quello che vedi in generale in cose come la data sono i metodi statici:

Date.UTC("some params"); 

Questo non è un costruttore corretta, però, questo è però

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

può andare macchina o transpile a ES5?

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

} 
2

Questo è l'esempio per molteplici costruttori in 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

E Immutabilità? usare il prototipo mette le proprietà pubbliche, giusto? –