how do I compare 2 functions in javascript

JavascriptFunction

Javascript Problem Overview


How do I compare 2 functions in javascript? I am not talking about internal reference. Say

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

Is it possible to compare a and b ?

Javascript Solutions


Solution 1 - Javascript

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

Solution 2 - Javascript

Closures mean that you need to be very careful what you mean when you say "compare". For example:

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

The ability to reach outside the function means that in a general sense, comparing functions is impossible.

However, in a practical sense you can get a very long way with Javascript parsing libraries like Esprima or Acorn. These let you build up an "Abstract Syntax Tree" (AST), which is a JSON description of your program. For example, the ast your return 1 functions looks like this

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

The AST has all the information you need to make comparisons - it is the Javascript function in data form. You could normalize variable names, check for closures, ignore dates and so on depending on your needs.

There are a bunch of tools and libraries to help simplify the process but even so, it's likely to be a lot of work and probably not practical, but it is mostly possible.

Solution 3 - Javascript

You can compare two variables that might contain function references to see if they refer to the exact same function, but you cannot really compare two separate functions to see if they do the same thing.

For example, you can do this:

function foo() {
    return 1;
}

var a = foo;
var b = foo;

a == b;   // true

But, you can't reliably do this:

function foo1() {
    return 1;
}

function foo2() {
    return 1;
}

var a = foo1;
var b = foo2;

a == b;   // false

You can see this second one here: http://jsfiddle.net/jfriend00/SdKsu/

There are some circumstances where you can use the .toString() operator on functions, but that's comparing a literal string conversion of your function to one another which, if even off by a teeny bit that is inconsequential to what it actually produces, will not work. I can think of no situation where I would recommend this as a reliable comparison mechanism. If you were seriously thinking about doing it this way, I'd ask why? What are you really trying to accomplish and try to find a more robust way of solving the problem.

Solution 4 - Javascript

toString() on a function returns the exact declaration. You can modify jfriend00's code to test it out.

This means you can test to see if your functions are exactly the same, including what spaces and newlines you put in it.

But first you have to eliminate the difference in their names.

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.

As the others said, this is unreliable because a single whitespace of difference makes the comparison false.

But what if you're employing it as a protective measure? ("Has someone altered my function since I created it?") You may actually desire this kind of strict comparison then.

Solution 5 - Javascript

ES6+ clean solution using template literals:

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

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

Basically means:

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

Solution 6 - Javascript

Convert function to string, then, replace line-break and space before comparing:

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: If you are using ES6, try to use let instead of var.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiononemachView Question on Stackoverflow
Solution 1 - JavascriptRony SPView Answer on Stackoverflow
Solution 2 - JavascriptJulian de BhalView Answer on Stackoverflow
Solution 3 - Javascriptjfriend00View Answer on Stackoverflow
Solution 4 - JavascriptAmaroqView Answer on Stackoverflow
Solution 5 - JavascriptWenfang DuView Answer on Stackoverflow
Solution 6 - JavascriptTânView Answer on Stackoverflow