如何在javascript中比较2个函数

时间:2012-03-22 06:47:28

标签: javascript function

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

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

是否可以比较ab

6 个答案:

答案 0 :(得分:50)

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

答案 1 :(得分:15)

关闭意味着当您说“比较”时,您需要非常小心。例如:

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

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

但是,从实际意义上讲,使用Javascript解析像Esprima或Acorn这样的库可以获得很长的路要走。这些可以让你构建一个“抽象语法树”(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具有进行比较所需的所有信息 - 它是数据形式的Javascript函数。您可以根据需要对变量名称进行规范化,检查闭包,忽略日期等。

有许多工具和库可以帮助简化流程,但即便如此,它可能需要做很多工作,而且可能不实用,但这种做法大多是可能的。

答案 2 :(得分:8)

你可以比较两个可能包含函数引用的变量,看看它们是否引用了完全相同的函数,但你无法真正比​​较两个独立的函数,看它们是否做同样的事情。

例如,您可以这样做:

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

答案 3 :(得分:2)

函数上的

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.

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

但是,如果你将它用作保护措施呢? (“自从我创建以来,有人改变了我的功能吗?”)你可能真的希望这种严格的比较。

答案 4 :(得分:0)

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

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:如果您使用的是ES6,请尝试使用let代替var

答案 5 :(得分:0)

使用 template literals 的 ES6+ 清洁解决方案:

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

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

基本上意味着:

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