10

how to compare two objects for equality if they have functions? lodash's isEqual works really well until functions are thrown in:

_.isEqual({
    a: 1,
    b: 2
}, {
    b: 2,    
    a: 1
});

// -> true

_.isEqual({
    a: 1,
    b: 2,
    c: function () {
        return 1;
    }
}, {
    a: 1,    
    b: 2,
    c: function () {
          return 1;
    }
});

// -> false
3
  • two anonymous function have two different prototypes, so two different objects! Commented May 13, 2015 at 10:37
  • It really depends on what you are going to compare. Best solution would be to create a hash unique per object and compare it, or, knowing the structure, make an equal function for that particular object. Commented May 13, 2015 at 10:40
  • Even though the functions do the same, they will never be equal. Do you want to ignore the functions and compare? Commented May 13, 2015 at 10:54

4 Answers 4

7

Are you sure you want to compare functions? If you only care about comparing every property that isn't a function, this is easy to do with lodash:

var o1 = { a: 1, b: 2, c: function() { return 1; } },
    o2 = { a: 1, b: 2, c: function() { return 1; } };

_.isEqual(o1, o2)
// → false

_.isEqual(_.omit(o1, _.functions(o1)), _.omit(o2, _.functions(o2)));
// → true

The functions() function returns a list of function properties, and using omit(), you can get rid of them.

Sign up to request clarification or add additional context in comments.

2 Comments

Since I was comparing complex objects, I needed to skip all functions: const isEqualExcludingFunctions = (a, b) => isEqualWith(a, b, (a, b) => (typeof a === 'function' || typeof b === 'function')?true:undefined); replace "||" with "&&" for a slightly stricter compare.
Note that this doesn't work for deep comparisons. If the function is nested, it won't be found by functions and won't be omitted.
6

This is what I tried:

_.isEqual(o1, o2, function(val1, val2) {
  if(_.isFunction(val1) && _.isFunction(val2)) {
    return val1.toString() === val2.toString();
  }
})

Lodash supports a customizer function which allows you to write your own equality checks. This seems to be a good enough test to see if the functions are character by character the same.

2 Comments

_.isEqualWith has this third customizer parameter lodash.com/docs/#isEqualWith
From the docs (helped me understand this answer better): 'If customizer returns undefined, comparisons are handled by the method instead.'
2

Try isEqualWith instead:

import { isEqualWith, isFunction } from 'lodash-es'

const o1 = { fn() {} }

const o2 = { fn() {} }

const equal = isEqualWith(o1, o2, (v1, v2) =>
  // if `customizer` returns `undefined`, comparisons are handled by the method instead
  isFunction(v1) && isFunction(v2) ? `${v1}` === `${v2}` : undefined,
)

console.log({ equal }) // { equal: true }

Comments

1

As the lodash documentation states:

Functions and DOM nodes are not supported.

https://lodash.com/docs#isEqual

1 Comment

They've since clarified this to Functions and DOM nodes are compared by strict equality, i.e. ===. I didn't check to see if the behavior actually changed or just the comment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.