我如何比较JavaScript中的2个函数

如何在JavaScript中比较2个函数? 我不是在谈论内部的参考。 说

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

可以比较ab吗?

 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( ) 

闭包意味着你说“比较”时要非常小心你的意思。 例如:

 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 

达到function之外的能力意味着从一般意义上说,比较function是不可能的。

但是,从实际意义上说,使用Esprima或Acorn等Javascriptparsing库可以获得很长的path。 这些让你build立一个“抽象语法树”(AST),它是你的程序的JSON描述。 例如,你的return 1函数看起来像这样

 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 

AST具有所有需要进行比较的信息 – 它是数据forms的Javascript函数。 你可以规范化variables名称,检查闭包,忽略date等,这取决于你的需要。

有许多工具和库可以帮助简化这个过程,但即使如此,这也可能是很多工作,可能并不实际,但这是可能的。

您可以比较两个可能包含函数引用的variables,以查看它们是否引用了完全相同的函数,但不能真正比较两个单独的函数来查看它们是否执行相同的操作。

例如,你可以这样做:

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

但是,你不能可靠地做到这一点:

 function foo1() { return 1; } function foo2() { return 1; } var a = foo1; var b = foo2; a == b; // false 

你可以在这里看到第二个: http : //jsfiddle.net/jfriend00/SdKsu/

在某些情况下,你可以在函数上使用.toString()运算符,但是它将你的函数的string转换相互比较,如果偶尔less了一点,这对实际产生的结果是无关紧要的工作。 我可以想象,我不会推荐这种可靠的比较机制。 如果你真的想这样做,我会问为什么? 你真正想要完成什么,并试图find解决问题的更强大的方法。

将函数转换为string,然后在比较之前replace换行符和空格:

 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 

函数的toString()返回确切的声明。 你可以修改jfriend00的代码来testing它。

这意味着你可以testing你的函数是否完全一样,包括你在其中放置了什么空格和换行符。

但首先你必须消除他们的名字的差异。

 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. 

正如其他人所说,这是不可靠的,因为一个空白的差异使得比较是错误的。

但是如果你把它作为保护措施呢? (“有人改变了我的function,因为我创build了它?”)你可能实际上渴望这种严格的比较。