web-dev-qa-db-fra.com

Comment tester l'égalité des fonctions en Javascript

Comment pourrais-je obtenir un test positif pour l'égalité de bar et foo?

 foo = function() {
    a = 1;
 }; 

 bar = function() {
    a = 1;
 }; 

 if (foo === bar) alert('baz');
 if (foo == bar) alert('qux');

Les deux conditions ci-dessus sont fausses.

Mise à jour - Comme demandé, la raison pour laquelle j'ai besoin de tester l'égalité de fonction

Je construis un framework Publish/Subscribe et je dois passer le rappel afin de me désabonner d'un sujet.

S'il vous plaît voir le violon: http://jsfiddle.net/jamiefearon/hecMS/47/

20
Jamie Fearon

Vous pouvez vérifier si le contenu de deux fonctions est exactement le même en comparant le résultat de l'appel de toString sur elles

 var foo = function() {
    a = 1;
 }; 

 var bar = function() {
    a = 1;
 }; 

alert(foo.toString() == bar.toString());​

Cependant, cela échouera s’il n’ya qu’un caractère différent. Vérifier si deux fonctions do la même chose, en revanche, est quasiment impossible.

23
Alex Turpin

Le problème est qu’il existe différentes notions d’égalité des fonctions.

  • Egalité de référence. Les fonctions sont stockées quelque part en mémoire et commencent à partir d'une adresse donnée. Pour deux noms de fonction (qui sont essentiellement des adresses à l'intérieur), l'égalité de référence vous donne true si les deux noms pointent vers la même adresse. C'est une question lorsque vous attribuez un bar = foo. L'égalité de référence est utilisée en JavaScript.
  • Egalité sur le code source telle que proposée dans une autre réponse. Cela ne fonctionnera pas si vous modifiez un caractère dans le corps de la fonction. De plus, toSource est actuellement (à partir de 2014) uniquement disponible dans Firefox, car il n'est pas standardisé par le W3C.
  • Égalités syntaxiques sur le code source. On pourrait utiliser des arbres à syntaxe abstraite pour résister aux modifications d’espaces et de commentaires. On pourrait utiliser l’équivalence alpha (c’est-à-dire l’équivalence de fonctions, dans lesquelles les variables sont renommées de manière cohérente), telle que définie dans le lambda calcul,
  • Egalité d'extension , lorsque les fonctions sont égales si elles fonctionnent de la même manière. Il y a un théorème indiquant qu'il n'y a aucun algorithme pour vérifier l'égalité des fonctions en extension, donc ce n'est certainement pas celui que vous recherchez. Cependant, dans certaines langues plus avancées que JS, il existe des
  • Égalité Intensionnelle (où vous prouvez que les fonctions sont égales à la main ou que votre programme ne compile pas) et
  • Égalité d’observation ( celle-ci est trop avancée pour expliquer ).

Alors, prends soin de ce que tu penses que l'égalité est.

19
polkovnikov.ph

Si vous regardez la source des événements Node.js

https://github.com/nodejs/node/blob/master/lib/events.js

vous pouvez voir que l'équipe principale utilise === pour comparer les fonctions à égalité.

Je ne sais pas comment === est implémenté pour les fonctions, mais j'espère bien que ce n'est pas toString(), car deux fonctions différentes pourraient avoir le même résultat toString().

4
Alexander Mills

Vous pouvez tester si deux variables référez au même objet fonction, et vous pouvez convertir des fonctions en chaînes et voir si elles sont vraiment identiques, mais en essayant de déterminer si deux fonctions font exactement même chose serait un peu plus difficile, ou peut-être beaucoup plus difficile.

Exécuter une paire de fonctions avec un minifier serait intéressant, car les minifiers effectuent une quantité considérable d’analyses statiques.

3
Pointy

Il semble que si vous avez besoin de cette fonctionnalité, il serait peut-être préférable de restructurer un peu votre programme. Quelque chose comme ça pourrait marcher:

function baz(myInt) { return 3 + myInt; }
function asd(a) { return 3 + a; }

var foo = baz;
foo(1); //returns 4

var bar = baz;
bar(3); //returns 6

foo === bar; //true

bar = asd;
bar(3); //returns 6

foo === bar; //false
1
BLSully

En gros, c'est impossible en général. Il n'y a aucun moyen de tester l'égalité fonctionnelle en javascript. Le plus proche que vous pouvez obtenir est de comparer leur code sous forme de chaîne pour l'égalité.

0
m4573r

Approche simple: si vous implémentez votre API d'abonnement pour renvoyer un ID unique chaque fois qu'il est appelé, il vous suffira alors d'appeler une API de désabonnement avec cet ID. En interne, dans un scénario simple, vous utiliseriez un tableau simple pour stocker tous les abonnés, mais avec cette approche, vous devrez stocker. Un identifiant peut être un simple compteur que vous pouvez incrémenter avec chaque appel abonné.

{ID: fonction de rappel de l'abonné}

Donc, parcourez tous les abonnés lorsque vous souhaitez publier à tous les abonnés.

Approche avancée: au lieu d'accepter un nom de fonction simple dans l'API d'abonnement, acceptez un objet d'une classe qui devrait avoir une fonction onMessage (ou le nom que vous souhaitez donner à cette méthode). Ensuite, vous pouvez simplement passer la même instance d'objet à l'API de désabonnement pour vous désinscrire. Lorsque vous devez notifier un abonné, vous pouvez appeler la fonction instance.onMessage de tous les abonnés. Comparer deux objets de référence est facile.

0
TechMaze