Question comment comparer 2 fonctions en javascript


Comment comparer 2 fonctions en javascript? Je ne parle pas de référence interne. Dire

var a = function(){return 1;};
var b = function(){return 1;};

Est-il possible de comparer a et b ?


36
2018-03-22 06:47


origine


Réponses:


var a = b = function( c ){ return c; };
//here, you can use a === b because they're pointing to the same memory and they're the same type

var a = function( c ){ return c; },
    b = function( c ){ return c; };
//here you can use that byte-saver Andy E used (which is implicitly converting the function to it's body's text as a String),

''+a == ''+b.

//this is the gist of what is happening behind the scences:

a.toString( ) == b.toString( )  

42
2018-03-22 06:54



Les fermetures signifient que vous devez faire très attention à ce que vous entendez par "comparer". Par exemple:

function closure( v ) { return function(){return v} };
a = closure('a'); b = closure('b');
[a(), b()]; // ["a", "b"]

// Now, are a and b the same function?
// In one sense they're the same:
a.toString() === b.toString(); // true
// In another sense they're different:
a() === b(); // false

La possibilité d'atteindre en dehors de la fonction signifie que, dans un sens général, la comparaison des fonctions est impossible.

Cependant, dans la pratique, vous pouvez obtenir un très long chemin avec les bibliothèques d'analyse syntaxique Javascript comme Esprima ou Acorn. Ceux-ci vous permettent de construire un "arbre de syntaxe abstraite" (AST), qui est une description JSON de votre programme. Par exemple, le ast de votre return 1 fonctions ressemble à ceci

ast = acorn.parse('return 1', {allowReturnOutsideFunction:true});
console.log( JSON.stringify(ast), null, 2)
{
  "body": [
    {
      "argument": {
        "value": 1,              // <- the 1 in 'return 1'
        "raw": "1",
        "type": "Literal"
      },
      "type": "ReturnStatement" // <- the 'return' in 'return 1'
    }
  ],
  "type": "Program"
}
// Elided for clarity - you don't care about source positions

L'AST a toutes les informations dont vous avez besoin pour faire des comparaisons - c'est la fonction Javascript sous forme de données. Vous pouvez normaliser les noms de variables, vérifier les fermetures, ignorer les dates, etc. selon vos besoins.

Il existe un grand nombre d’outils et de bibliothèques pour simplifier le processus, mais malgré tout, cela risque d’avoir beaucoup de travail et probablement de ne pas être pratique, mais c’est surtout possible.


13
2017-08-18 00:39



Vous pouvez comparer deux variables pouvant contenir des références de fonction pour voir si elles font référence à la même fonction, mais vous ne pouvez pas vraiment comparer deux fonctions distinctes pour voir si elles font la même chose.

Par exemple, vous pouvez faire ceci:

function foo() {
    return 1;
}

var a = foo;
var b = foo;

a == b;   // true

Mais, vous ne pouvez pas le faire de manière fiable:

function foo1() {
    return 1;
}

function foo2() {
    return 1;
}

var a = foo1;
var b = foo2;

a == b;   // false

Vous pouvez voir ce second ici: http://jsfiddle.net/jfriend00/SdKsu/

Il y a certaines circonstances où vous pouvez utiliser le .toString() operator on functions, mais en comparant une conversion de chaîne littérale de votre fonction à une autre qui, même si elle est atténuée par un bit minuscule sans conséquence sur ce qu’elle produit réellement, ne fonctionnera pas. Je ne peux penser à aucune situation où je recommanderais ceci comme mécanisme de comparaison fiable. Si vous pensiez sérieusement à le faire de cette façon, je vous demanderais pourquoi? Qu'est-ce que vous essayez vraiment d'accomplir et essayez de trouver un moyen plus solide de résoudre le problème?


8
2018-03-22 06:55



Convertissez la fonction en chaîne, puis remplacez le saut de ligne et l'espace avant de comparer:

let a = function () {
  return 1
};

let b = function () {
  return 1
};

a = a.toString().replace(/\n/g, '').replace(/\s{2}/g, ' ');
b = b.toString().replace(/\n/g, '').replace(/\s{2}/g, ' ');

console.log(a); // 'function () { return 1}'
console.log(b); // 'function () { return 1}'
console.log(a === b); // true

b = function () {
  return 2
};

b = b.toString().replace(/\n/g, '').replace(/\s{2}/g, ' ');

console.log(b); // 'function () { return 2}'
console.log(a === b); // false

b = () => 3;

b = b.toString().replace(/\n/g, '').replace(/\s{2}/g, ' ');

console.log(b); // '() => 3'
console.log(a === b); // false

p / s: Si vous utilisez ES6, essayez d'utiliser let au lieu de var.


0
2017-08-25 11:59



toString () sur une fonction renvoie la déclaration exacte. Vous pouvez modifier le code de jfriend00 pour le tester.

Cela signifie que vous pouvez tester pour voir si vos fonctions sont exactement les mêmes, y compris les espaces et les nouvelles lignes que vous y mettez.

Mais vous devez d'abord éliminer la différence de noms.

function foo1() {
    return 1;
}

function foo2() {
    return 1;
}

//Get a string of the function declaration exactly as it was written.
var a = foo1.toString();
var b = foo2.toString();

//Cut out everything before the curly brace.
a = a.substring(a.indexOf("{"));
b = b.substring(b.indexOf("{"));

//a and b are now this string:
//"{
//    return 1;
//}"
alert(a == b); //true.

Comme les autres l’ont dit, cela n’est pas fiable car un seul espace de différence rend la comparaison fausse.

Mais si vous l'employez comme mesure de protection? ("Quelqu'un a-t-il modifié ma fonction depuis que je l'ai créé?") Vous pouvez en fait souhaiter ce type de comparaison stricte alors.


0
2017-11-15 05:49