2012-03-22 38 views
31

¿Cómo comparo 2 funciones en javascript? No estoy hablando de referencia interna. Dicencómo puedo comparar 2 funciones en javascript

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

¿Es posible comparar a y b?

+0

Que JavaScript ni siquiera analizará un error de sintaxis ... pero, ¿qué quiere decir con "comparar"? Varios navegadores admiten "toString" en objetos de función de manera diferente, por lo que puede funcionar en su caso. (Pero no en este caso porque no analizará por lo que no hay nada asignado a 'a' o' b'). También creo que hay algunas bibliotecas para "reflejar" en JavaScript [en bloques de script]. –

+0

, ya que todo es un objeto en JS, es probable que intente encontrar una comparación de objetos similar (http://stackoverflow.com/questions/1068834/object-comparison-in-javascript) – shershen

Respuesta

37
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() 
+2

tenga en cuenta que esto funciona con funciones anónimas (que , es suficiente, es lo que pidió OP). Si tienes var a = function a() {.... y var b = function b() {... (que mucha gente hace, porque entonces obtienes mensajes más significativos en tu pila) entonces no hay manera de que – gotofritz

8

Puede comparar dos variables que pueden contener referencias de las funciones para ver si se refieren a la misma función exacta, pero realmente no se puede comparar dos funciones separadas para ver si ellos hacen lo mismo.

Por ejemplo, se puede hacer esto:

function foo() { 
    return 1; 
} 

var a = foo; 
var b = foo; 

a == b; // true 

embargo, no se puede hacer esto de forma fiable:

function foo1() { 
    return 1; 
} 

function foo2() { 
    return 1; 
} 

var a = foo1; 
var b = foo2; 

a == b; // false 

se puede ver este segundo aquí: http://jsfiddle.net/jfriend00/SdKsu/

Hay son algunas circunstancias en las que puede usar el operador .toString() en funciones, pero eso es comparar una conversión de cadena literal de su función a otra que, yo Incluso un poco que no tiene importancia para lo que realmente produce, no funcionará. No puedo pensar en ninguna situación en la que recomendaría esto como un mecanismo de comparación confiable. Si estuvieras pensando seriamente en hacerlo de esta manera, preguntaría ¿por qué? ¿Qué es lo que realmente intenta lograr y tratar de encontrar una forma más sólida de resolver el problema?

12

Los cierres significan que debe tener mucho cuidado con lo que quiere decir cuando dice "comparar". Por ejemplo:

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 capacidad de llegar fuera de la función significa que en un sentido general, la comparación de las funciones es imposible.

Sin embargo, en un sentido práctico puede recorrer un largo camino con las librerías de análisis de JavaScript como Esprima o Acorn. Estos le permiten crear un "Árbol de sintaxis abstracta" (AST), que es una descripción JSON de su programa. Por ejemplo, el ast sus funciones return 1 se parece a esto

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 

El AST tiene toda la información que necesita para hacer comparaciones - es la función Javascript en forma de datos. Puede normalizar nombres de variables, verificar cierres, ignorar fechas, etc. según sus necesidades.

Hay un conjunto de herramientas y bibliotecas para ayudar a simplificar el proceso, pero aun así, es probable que sea mucho trabajo y probablemente no sea práctico, pero es más que nada posible.

0

función Convertir a cadena, entonces, reemplazar salto de línea y el espacio antes de comparar:

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 está utilizando ES6, trate de usar let en lugar de var .

+0

¿No funciona si declara la función como "función a() {return 1;}"? –

+0

@TarekSalahuddinMahmud Puedes intentarlo de nuevo. Solo compruebo de nuevo. Esta funcionando. –

0

toString() en una función devuelve la declaración exacta. Puedes modificar el código de jfriend00 para probarlo.

Esto significa que puede probar para ver si sus funciones son exactamente las mismas, incluidos los espacios y líneas nuevas que coloca en él.

Pero primero tienes que eliminar la diferencia en sus nombres.

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. 

Como dijeron los demás, esto no es confiable porque un solo espacio en blanco de diferencia hace que la comparación sea falsa.

¿Pero qué pasa si lo está empleando como medida de protección? ("¿Alguien ha alterado mi función desde que la creé?") En realidad, puede que desee este tipo de comparación estricta.

Cuestiones relacionadas