Compare Objects with Lodash
Lodash has an isEqual()
function that checks if two values are deeply equal. This function is different from the ===
operator, which only checks if two objects are the exact same reference:
const obj1 = {
name: 'Will Riker',
rank: 'Commander',
age: 29
};
const obj2 = {
name: 'Will Riker',
rank: 'Commander',
age: 29
};
obj1 === obj1; // true
// `===` only checks if two objects are the same reference, not if the
// the two objects have the exact same keys and values.
obj1 === obj2; // false
// Lodash's `isEqual()` checks if the two objects have the same keys
// and values:
_.isEqual(obj1, obj2); // true
When comparing primitive values, the isEqual()
function uses SameValueZero semantics, which means that NaN
is considered equal to itself, and +0
is considered equal to -0
.
_.isEqual({ x: NaN }, { x: NaN }); // true
_.isEqual({ x: +0 }, { x: -0 }); // true
Built-in Classes
In addition, isEqual()
is smart enough to compare arrays, dates, Number
instances, and other built-in classes:
const obj1 = {
date: new Date('2020/06/01'),
num: new Number(1)
};
const obj2 = {
date: new Date('2020/06/01'),
num: 1
};
_.isEqual(obj1, obj2); // true
This makes isEqual()
ideal for checking if two POJOs have the same data.
With Classes
The isEqual()
function treats two objects as different if they are instances of different classes. For example,
even though the two objects in the below example have the same keys and values, they are different because obj2
is an instance of the Character
class and obj1
is not.
const obj1 = { name: 'Will Riker', rank: 'Commander' };
class Character {}
const obj2 = new Character();
Object.assign(obj2, { name: 'Will Riker', rank: 'Commander' });
_.isEqual(obj1, obj2); // false
Depending on your use case, this may be an issue. However, in general, you should only use isEqual()
for
comparing POJOs as opposed to complex classes. In particular, if you want to compare Mongoose documents, you should convert the document to a POJO using toObject()
first:
const Character = mongoose.model('Character', Schema({
_id: false,
name: String,
age: Number
}));
const doc = new Character({ name: 'Will Riker', age: 29 });
// false, because `doc` is a document, not a POJO
_.isEqual(doc, { name: 'Will Riker', age: 29 });
// true
_.isEqual(doc.toObject(), { name: 'Will Riker', age: 29 });