2009-08-13 11 views
4

Le problème est que je dois créer une nouvelle instance de la classe passéusine JavaScript avec des arguments optionnels

Est-il possible de réécrire cette fonction, il pourrait accepter un certain nombre d'arguments?

function createInstance(ofClass, arg1, arg2, arg3, ..., argN){ 
    return new ofClass(arg1, arg2, arg3, ..., argN); 
} 

Cette fonction doit créer une instance de la classe transmise. Exemple:

var SomeClass = function(arg1, arg2, arg3){ 
    this.someAttr = arg3; 
    ..... 
} 
SomeClass.prototype.method = function(){} 

var instance = createInstance(SomeClass, 'arg1', 'arg2', 'arg3'); 

Cela devrait donc être vrai. Pour l'instant, je viens de limiter N à 25, avec l'espoir que plus d'arguments sont rarement utilisés.

+1

Avez-vous lu l'article de John Resig (lié ci-dessous)? Ça va faire ce que vous voulez (bien que vous aurez besoin de code supplémentaire pour le faire, bien sûr.) Je ne peux pas penser à un autre moyen de simuler un appel à 'new'. La façon dont Resig explique que c'est ce que j'ai vu dans toutes les librairies JavaScript avec une génération de classe dynamique (MooTools par exemple.) – Blixt

+0

Merci, je vais aller avec votre solution. –

+0

Cela a la bonne réponse: http://stackoverflow.com/questions/5054926/javascript-create-instance-with-array-of-arguments –

Répondre

10

Les autres réponses sont sur la bonne voie, mais aucun d'entre eux mentionnent que vous devez être conscient du fait que arguments est pas un Array. C'est une structure spéciale qui se comporte comme Array.

Alors avant de l'utiliser comme un Array, vous pouvez le convertir en un comme ceci:

function createInstance(cls) { 
    // This will use the slice function of the Array type, effectively converting 
    // the arguments structure to an Array and throwing away the first argument, 
    // which is cls. 
    var args = Array.prototype.slice.call(arguments, 1); 
    return cls.apply(this, args); 
} 

Désolé, je viens de copier le code avec constructor etc., et ne pas penser à ce qu'il fait faire. Je l'ai mis à jour maintenant à ce que vous voulez. Vous constaterez qu'il appelle le constructeur sansnew, donc vous n'aurez pas le même comportement. Cependant, John Resig (auteur de jQuery) wrote on this very issue. Donc, d'après l'article de John Resig, vous avez deux façons de le résoudre. La solution la plus élaborée sera la plus transparente pour l'utilisateur, mais c'est à vous de choisir la solution que vous choisissez.


Voici une solution « parfaite » si vous ne souhaitez soutenir les navigateurs qui ont la fonction Object.create (ce qui est un assez grand pourcentage maintenant par rapport à il y a trois ans):

function createInstance(cls) { 
    var obj = Object.create(cls.prototype); 

    var args = Array.prototype.slice.call(arguments, 1); 
    cls.apply(obj, args); 

    return obj; 
} 

Le résultat les objets des deux new cls(x) et createInstance(cls, x) doivent être identiques.

+0

Désolé, ma question n'était pas assez claire, le problème est que j'ai besoin d'une nouvelle instance d'obj, donc votre réponse ne résout pas mon problème problème, mais upvoted pour mentionner que les arguments ne sont pas un tableau. –

+0

Je comprends mieux votre question maintenant. Lisez ma mise à jour pour savoir comment résoudre votre problème. – Blixt

+1

J'apprécierais une explication pour -1, d'autant plus que c'est la seule réponse qui, à ma connaissance, fonctionne (en prenant en compte le changement de John Resig.) Je vois quelqu'un finalement évoqué 'eval' en tant que solution, mais je ne le toucherais pas avec un bâton, j'en ai peur. – Blixt

4

Il y a toujours un arguments array

+0

Je sais à ce sujet, s'il vous plaît donner un exemple comment voulez-vous utiliser pour réécrire cette fonction. –

+0

Pourriez-vous donner un exemple concret? Avez-vous à passer tous les arguments dans le constructeur? La réponse de Djko ne fonctionne-t-elle pas? http: // stackoverflow.com/questions/1271657/javascript-factory-with-optional-arguments/1271673 # 1271673 –

Questions connexes