2009-02-17 6 views
3

Donc j'avoue que je suis nouveau à javascript et que je viens d'un arrière-plan C. + ("Salut, je suis Bob, je suis un utilisateur de langage statique de classe", chorus "salut Bob!")."surcharge de méthode" en javascript

je trouve que je finis souvent par écrire des fonctions telles que:

function someFunc() 
{ 
    if (arguments.length === 0){ 
     ... 
    } else { 
     ... 
    } 
} 

(où il pourrait y avoir trois cas). Ou, encore, j'écris la différence dans le nom:

function someFuncDefault() { ... }; 
function someFuncRealArg(theArg) { ... }; 

(suppléant "RealArg" pour une phrase sémantiquement pourvues d'un contenu).

Y at-il un meilleur modèle pour ce genre de chose?

+0

Isn » t-ce un exemple de méthode overLOADing? –

+1

Je recommande fortement les vidéos de Douglas Crockford pour l'apprentissage de javascript ... ils m'ont aidé à comprendre comment tout cela s'accorde: http://video.yahoo.com/search/?p=javascript – Akrikos

Répondre

5

Jetez un oeil à this post.

+0

Neat! Pas quelque chose que je recommanderais pour un débutant (si quelque chose s'est mal passé ...) mais très cool! – Akrikos

+0

Après avoir regardé sa question, je pense que c'est la meilleure option pour ce qu'il veut faire. Sinon, il pourrait essayer d'attacher des méthodes aux objets, mais je ne pense pas que cela l'aidera dans ce cas. – Akrikos

+0

Je me retrouve généralement avec l'approche de Grant Wagner puisque la plupart des fonctions qui reçoivent des arguments variables ont une grande partie du code en commun pour chaque combinaison d'arguments. – Hoffmann

3

Je ne sais pas que je le ferais de cette façon, mais il semble que cela pourrait rendre votre code légèrement moins ingérable:

function someFunc() { 
    switch (arguments.length) { 
     case 0: noArgs(); 
     case 1: oneArg(arguments[0]); 
     case 2: twoArgs(arguments[0], arguments[1]); 
    } 
    function noArgs() { 
     // ... 
    } 
    function oneArg(a) { 
     // ... 
    } 
    function twoArgs(a, b) { 
     // ... 
    } 
} 

Un autre exemple pourrait être:

function someFunc(a, b) { 
    if ('string' == typeof a) { 
     // ... 
    } else if ('number' == typeof a) { 
     // ... 
    } 
} 

Et Bien sûr, vous pouvez probablement créer quelque chose d'assez ingérable en combinant les deux exemples (en utilisant des conditions pour déterminer le comportement en fonction du nombre d'arguments et des types d'arguments).

+0

Je n'ai jamais connu le tableau d'arguments avant. C'est fantastique! – notnot

+0

Je ne vois pas comment les valeurs retournées par les fonctions imbriquées dans votre exemple sont traitées –

+0

Je n'aime pas ça ... il ne contourne pas vraiment son problème d'encombrement dans la base de code, il lui donne juste un manière différente d'avoir plus de méthodes avec des noms drôles. – Akrikos

1

En Javascript, tous les arguments sont facultatifs.

Vous pouvez essayer quelque chose comme:

Edit (meilleure méthode qui ne rompt pas pour les valeurs dont 'truthiness' est faux):

function bar(arg1, arg2) { 
    if(arg1 === undefined) { set default } 
    if(arg2 === undefined) { set default } 
    //do stuff here 
} 

méthode ancienne qui casse pour les valeurs Falsey:

function foo(arg1, arg2) { 
    if(!arg1) { set default } 
    if(!arg2) { set default } 
    //do stuff here 
} 

Un excellent endroit pour commencer avec le javascript sont des conférences javascript Douglas Crockford: http://video.yahoo.com/search/?p=javascript

+0

Une chute potentielle de cette approche est que vous souhaitiez être en mesure de transmettre à votre fonction un élément évalué comme faux (tel que 0). La fonction typeof pourrait être plus sûre. –

+0

vrai ... J'ai pensé à mettre cette mise en garde, mais j'ai oublié en écrivant :-( – Akrikos

+0

hmm ... il semble que j'ai mal lu la question, il fait déjà quelque chose de similaire. – Akrikos

0

Javascript vous permet d'être vraiment paresseux avec ceci (pas aussi paresseux que Python, mais assez paresseux).

function someFunc(arg1, arg2) 
{ 
    if(typeof(arg1) == "undefined") { 
    arg1 = default; 
    } 
    ... 
} 

Vous n'avez donc pas vraiment besoin de surcharger. Javascript ne vous criera pas de passer le mauvais nombre de paramètres.

+0

Veuillez corriger la faute d'orthographe de undefined – Akrikos

+0

Y a-t-il une raison pour que vous vérifiiez 'typeof' plutôt que d'utiliser simplement === le mot réservé javascript undefined? – Akrikos

+0

Mon instinct me dit que c'est parce que certains navigateur qui foutu Javascript n'a pas défini indéfini comme un mot réservé, mais je ne sais pas à coup sûr. –

1

Ceci est en surcharge, non prioritaire non?

Javascript est faiblement typé, donc les signatures de méthodes et le support natif sont supprimés. Ma recommandation est de passer un objet extensible comme argument solitaire. Inspecter et gérer l'existance des propriétés sur l'objet param comme vous le souhaitez.

Quel avantage cela at-il sur les arguments? Eh bien, cela vous permet d'être explicite sur vos intentions là où vous appelez, et sans ambiguïté sur la signification de arg1 et arg2 où vous recevez, et cela vous permet de faire abstraction d'une classe d'objets de données personnalisée à laquelle vous pouvez étendre la fonctionnalité.

function someFunc(params) 
{ 
    var x = params.x || defaultX; 
    var y = params.y || defaultY; 

    //businesslogic 
} 

someFunc({x:'foo',y:'bar'}); 

someFunc({y:'baz'}); 
+0

Intéressant. Est-ce que cela fonctionne si x ou y sont des booléens 'faux'? – JBRWilkinson

+0

est non, mais considérez ceci comme un exemple - 'typeof (params.x)! = 'Non défini'? params.x: defaultX; 'serait plus approprié – annakata

0

Tout le monde est venu près, je pense que la vraie question ici est que JavaScript vous ne devriez pas modifier le comportement en fonction des paramètres étant transmis.

Depuis JavaScript fait tous les paramètres optionnels que vous pouvez suivre le Concise méthode d'utilisation de cette convention:

function foo(bar, baz) { 
    bar = bar || defaultBar; 
    baz = baz || defaultBaz; 
    . 
    . 
    . 
} 
0

Personnellement, je préfère écrire la fonction la plus complexe qui serait effectué, puis documenter dans les commentaires afin que les autres savent qu'ils ne pas doivent envoyer tous les arguments.

//concat(str1, str2 [,str3 [,str4 [,str5]]]) 
function concat(str1, str2, str3, str4, str5) { 
    var str = str1 + str2; 
    if(str3 != undefined) 
     str += str3; 
    if(str4 != undefined) 
     str += str4; 
    if(str5 != undefined) 
     str += str5; 
    return str; 
} 

J'ai aussi trouvé des situations où l'ordre d'argument d'importance dans une fonction normale, mais parfois je voudrais envoyer les arguments séparement (à savoir que je voudrais envoyer str3 et STR5 mais pas str4). Pour cela, j'utiliser un objet et de tester les propriétés connues

//concat({str1:string, str2:string, str3:string, str4:string, str5:string}) 
//str3, str4, and str5 are optional 
function concat(strngs) { 
    var str = strngs.str1 + strngs.str2; 
    if(strngs.str3 != undefined) 
     str += strngs.str3; 
    if(strngs.str4 != undefined) 
     str += strngs.str4; 
    if(strngs.str5 != undefined) 
     str += strngs.str5; 
    return str; 
} 
0

Un peu mécanisme de surcharge plus complet est offert par bob.js:

var notify = new bob.fn.overloadFunction([ 
    { 
     condition: function(msg) { return bob.utils.isString(msg); }, 
     overload: function(msg) { 
      console.log(msg); 
     } 
    }, 
    { 
     condition: function(bSayHello) { return bob.utils.isBoolean(bSayHello); }, 
     overload: function(bSayHello, msg) { 
      msg = bSayHello ? 'Hello: ' + msg : msg; 
      console.log(msg); 
     } 
    } 
]); 

appel de la fonction surchargée:

notify('Simple sentence.'); 
// Output: 
// Simple sentence. 
notify(true, 'Greeting sentence.'); 
// Output: 
// Hello: Greeting sentence. 
notify(123); 
// JavaScript Error: 
// "No matching overload found."