907 votes

Fonction d’une surcharge en Javascript - meilleures pratiques

Quelle est la meilleure façon (s) Fake surcharge de fonctions en Javascript ?

Je sais que ce n'est pas possible de surcharger des fonctions en Javascript, comme dans d’autres langues. Si j’avais besoin d’une fonction avec deux utilise foo(x) et foo(x,y,z) qui est le moyen le meilleur / plu :

  1. En utilisant des noms différents en premier lieu
  2. Avec des arguments facultatifs, comme y = y || « par défaut »
  3. En utilisant le nombre d’arguments
  4. Vérification des types d’arguments
  5. Ou comment ?

716voto

epascarello Points 71353

La meilleure façon de faire fonction de surcharge avec des paramètres est ne pas de vérifier la longueur de l’argument ou les types ; vérifier les types vont juste faire votre code lent et vous avez le plaisir de tableaux, nulls, objets, etc..

Que faire la plupart des développeurs est de virer sur un objet comme dernier argument à leurs méthodes. Cet objet peut contenir n’importe quoi.

Puis vous pouvez le gérer en tout cas vous voulez dans votre méthode. [Switch, if-else, etc..]

196voto

rocketsarefast Points 1167

Je fais souvent ce:

C#:

public string CatStrings(string p1)                  {return p1;}
public string CatStrings(string p1, int p2)          {return p1+p2.ToString();}
public string CatStrings(string p1, int p2, bool p3) {return p1+p2.ToString()+p3.ToString();}

CatStrings("one");        // result = one
CatStrings("one",2);      // result = one2
CatStrings("one",2,true); // result = one2true

JavaScript Équivalent:

function CatStrings(p1, p2, p3)
{
  var s = p1;
  if(typeof p2 !== "undefined") {s += p2;}
  if(typeof p3 !== "undefined") {s += p3;}
  return s;
};

CatStrings("one");        // result = one
CatStrings("one",2);      // result = one2
CatStrings("one",2,true); // result = one2true

Cet exemple particulier est en fait plus élégant en javascript qu'en C#. Les paramètres qui ne sont pas spécifiés sont nul en javascript, qui évalue à false dans une instruction if. Comme d'autres l'ont dit, si 'null' est un paramètre valide, cette méthode échoue. Aussi, la définition de la fonction ne pas transmettre les informations que p2 et p3 sont facultatifs. Si vous avez besoin d'un lot de surcharge, jQuery a décidé d'utiliser un objet en tant que paramètre, par exemple, jQuery.ajax(options). Je suis d'accord avec eux que c'est le plus puissant et clairement consignées approche de la surcharge, mais j'ai rarement besoin de plus d'un ou deux paramètres facultatifs.

EDIT: changé SI test par Ian suggestion

119voto

Gumbo Points 279147

Il n’y a aucune fonction réelle surcharge en JavaScript car il permet de passer n’importe quel nombre de paramètres de tout type. Vous devez vérifier à l’intérieur de la fonction combien arguments ont été transmis et quel genre ils sont.

27voto

t3rse Points 5983

Il y a deux façons vous pourriez mieux se rapprocher de cela :

  1. Passer un dictionnaire (associatif) si vous voulez laisser une grande flexibilité
  2. Prenez un objet comme argument et utiliser l’héritage de prototype basé à ajouter la flexibilité.

22voto

Keldon Alleyne Points 1399

Voici un test de référence sur la fonction de surcharge - http://goo.gl/UyYAD (code indiqué dans ce post). Il montre que la fonction de surcharge (en prenant les types de compte) peut être autour de 13 fois plus lent dans Google Chrome V8 de 16.0(bêta).

Ainsi que le passage d'un objet (c - {x: 0, y: 0}), on peut aussi prendre le C approche cas échéant, de nommer les méthodes en conséquence. Par exemple, le Vecteur.AddVector(vecteur), Vecteur.AddIntegers(x, y, z, ...) et de Vecteur.AddArray(integerArray). Vous pouvez regarder les bibliothèques C, telles que OpenGL pour le nommage de l'inspiration.

Edit: j'ai ajouté une référence pour le passage d'un objet et d'essais pour l'objet à l'aide de deux 'param' in arg et arg.hasOwnProperty('param'), et la fonction de surcharge est beaucoup plus rapide que de passer un objet et la vérification de propriétés (dans ce cas-test au moins).

À partir d'une conception de point de vue, la fonction de surcharge n'est valable que logique ou si la surcharge des paramètres correspondent à la même action. Il va de soi qu'il doit y avoir un sous-jacente méthode qui n'est concerné avec des détails précis, sinon ça peut indiquer inapproprié des choix de conception. Donc, on pourrait également résoudre l'utilisation de la surcharge de fonction par la conversion des données à l'objet concerné. Bien sûr, il faut tenir compte de l'étendue du problème comme il n'y a pas besoin d'en faire des dessins si votre intention est simplement d'imprimer un nom, mais pour la conception de cadres et de bibliothèques telles pensée est justifiée.

Mon exemple est tiré d'un Rectangle de mise en œuvre - d'où la mention de la Dimension et de Point de. Peut-être Rectangle pourrait ajouter un GetRectangle() méthode de l' Dimension et Point prototype, et ensuite la fonction de surcharge question est triée. Et que dire de primitives? Eh bien, nous avons argument de la longueur, qui est maintenant un test valide puisque les objets ont un GetRectangle() méthode.

function Dimension() {}
function Point() {}

var Util = {};

Util.Redirect = function (args, func) {
  'use strict';
  var REDIRECT_ARGUMENT_COUNT = 2;

  if(arguments.length - REDIRECT_ARGUMENT_COUNT !== args.length) {
    return null;
  }

  for(var i = REDIRECT_ARGUMENT_COUNT; i < arguments.length; ++i) {
    var argsIndex = i-REDIRECT_ARGUMENT_COUNT;
    var currentArgument = args[argsIndex];
    var currentType = arguments[i];
    if(typeof(currentType) === 'object') {
      currentType = currentType.constructor;
    }
    if(typeof(currentType) === 'number') {
      currentType = 'number';
    }
    if(typeof(currentType) === 'string' && currentType === '') {
      currentType = 'string';
    }
    if(typeof(currentType) === 'function') {
      if(!(currentArgument instanceof currentType)) {
        return null;
      }
    } else {
      if(typeof(currentArgument) !== currentType) {
        return null;
      }
    } 
  }
  return [func.apply(this, args)];
}

function FuncPoint(point) {}
function FuncDimension(dimension) {}
function FuncDimensionPoint(dimension, point) {}
function FuncXYWidthHeight(x, y, width, height) { }

function Func() {
  Util.Redirect(arguments, FuncPoint, Point);
  Util.Redirect(arguments, FuncDimension, Dimension);
  Util.Redirect(arguments, FuncDimensionPoint, Dimension, Point);
  Util.Redirect(arguments, FuncXYWidthHeight, 0, 0, 0, 0);
}

Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X