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

IT技术 javascript function
2021-02-08 09:21:43

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

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

可以比较ab吗?

6个回答
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( )  
请注意,这适用于匿名函数(这很公平,这是 OP 所要求的)。如果你有 var a = function a(){.... 和 var b = function b(){...(很多人都这样做,因为那样你会在你的堆栈中得到更有意义的消息)那么没有办法
2021-03-24 09:21:43
请注意,这也将对true具有相同代码的两个不同函数进行评估(可能在实际使用两个类方法时发生)。
2021-04-04 09:21:43
请注意,如果您的函数引用在其包含范围内定义的任何变量,toString则即使函数实际上并不相等相等性检查也可能返回 true。例如,请参阅 Julian 的回答
2021-04-09 09:21:43
请注意,对于具有相同语法树但具有不同间距的函数,此方法将失败。
2021-04-10 09:21:43

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

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

能够到达函数之外,意味着在一般意义上,比较函数是不可能的。

但是,在实际意义上,您可以使用 Esprima 或 Acorn 等 Javascript 解析库获得很大的帮助。这些让你建立一个“抽象语法树”(AST),它是你的程序的 JSON 描述。例如,你的return 1函数的 ast看起来像这样

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 包含进行比较所需的所有信息——它是数据形式的 Javascript 函数。您可以根据需要标准化变量名称、检查闭包、忽略日期等。

有很多工具和库可以帮助简化流程,但即便如此,这可能需要大量工作,而且可能不切实际,但大多数情况下是可能的。

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

例如,您可以这样做:

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()在函数上使用运算符,但这是将函数的文字字符串转换与另一个进行比较,即使有一点点与实际产生的结果无关紧要,也不会起作用。我想不出在任何情况下我会推荐它作为一种可靠的比较机制。如果你认真考虑这样做,我会问为什么?您真正想要完成什么并尝试找到解决问题的更强大的方法。

函数上的 toString() 返回准确的声明。你可以修改jfriend00的代码来测试一下。

这意味着您可以测试您的函数是否完全相同,包括您在其中放置了哪些空格和换行符。

但首先你必须消除它们名称上的差异。

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.

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

但是,如果您将其用作保护措施呢?(“自从我创建函数以来,有人更改过我的函数吗?”)那时您可能真的希望进行这种严格的比较。

使用模板文字的ES6+ 清洁解决方案

const fn1 = () => {}
const fn2 = () => {}

console.log(`${fn1}` === `${fn2}`) // true

基本上是指:

console.log(fn1.toString() === fn2.toString()) // true