deep-eql vs deep-equal vs fast-equals
Deep Equality Comparison Comparison
1 Year
deep-eqldeep-equalfast-equalsSimilar Packages:
What's Deep Equality Comparison?

Deep equality comparison libraries in JavaScript are tools that allow developers to compare two values (such as objects, arrays, or primitives) to determine if they are structurally identical, meaning they have the same properties, values, and nested structures. Unlike shallow comparison, which only checks the top-level properties, deep equality comparison traverses the entire structure of the values being compared. This is particularly useful in scenarios like testing, state management, and data validation, where understanding whether two complex values are equivalent is crucial. deep-eql is a robust library that handles complex comparisons, including circular references and custom equality functions. deep-equal is a lightweight and straightforward library for deep equality checks, focusing on simplicity and performance. fast-equals is an optimized library designed for high-performance deep equality comparisons, particularly for arrays and objects, making it suitable for performance-sensitive applications.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
deep-eql22,009,77011223.9 kB21a year agoMIT
deep-equal21,322,85879290.3 kB42 years agoMIT
fast-equals11,926,411535345 kB67 months agoMIT
Feature Comparison: deep-eql vs deep-equal vs fast-equals

Performance

  • deep-eql:

    deep-eql is not optimized for performance, especially with large or deeply nested structures. Its focus on accuracy and handling edge cases can lead to slower comparisons in some scenarios, making it less suitable for performance-critical applications.

  • deep-equal:

    deep-equal offers reasonable performance for most deep equality checks, but it does not include optimizations for specific data types. Its simplicity means that it does not have the overhead of complex algorithms, but it may not be the fastest option for large or nested structures.

  • fast-equals:

    fast-equals is designed for high performance, particularly when comparing arrays and objects. It uses optimized algorithms to reduce the time complexity of comparisons, making it one of the fastest libraries for deep equality checks, especially in performance-sensitive applications.

Handling Circular References

  • deep-eql:

    deep-eql handles circular references gracefully, allowing for comparisons of objects that reference themselves or each other. This is particularly useful for comparing complex data structures like trees or graphs, where circular references can occur.

  • deep-equal:

    deep-equal does not handle circular references by default, which can lead to infinite loops and stack overflow errors when comparing such structures. It is important to ensure that the data being compared is free of circular references to avoid issues.

  • fast-equals:

    fast-equals does not explicitly handle circular references, but its performance characteristics make it less prone to issues with them. However, like deep-equal, it is recommended to avoid comparing structures with circular references to prevent potential problems.

Customization

  • deep-eql:

    deep-eql allows for customization through the use of equality functions, which can be provided as options to handle specific types of comparisons. This flexibility makes it suitable for scenarios where default equality checks are not sufficient.

  • deep-equal:

    deep-equal does not provide much customization beyond the default deep equality algorithm. It is designed to be simple and straightforward, with little room for modification or extension.

  • fast-equals:

    fast-equals supports customization by allowing users to provide their own comparison functions for specific types. This feature adds flexibility while maintaining the library's focus on performance.

Code Example

  • deep-eql:

    Deep Comparison with deep-eql

    const deepEql = require('deep-eql');
    
    const obj1 = { a: 1, b: { c: 2 } };
    const obj2 = { a: 1, b: { c: 2 } };
    const obj3 = { a: 1, b: { c: 3 } };
    
    console.log(deepEql(obj1, obj2)); // true
    console.log(deepEql(obj1, obj3)); // false
    
  • deep-equal:

    Deep Comparison with deep-equal

    const deepEqual = require('deep-equal');
    
    const obj1 = { a: 1, b: { c: 2 } };
    const obj2 = { a: 1, b: { c: 2 } };
    const obj3 = { a: 1, b: { c: 3 } };
    
    console.log(deepEqual(obj1, obj2)); // true
    console.log(deepEqual(obj1, obj3)); // false
    
  • fast-equals:

    Fast Deep Comparison with fast-equals

    const { equals } = require('fast-equals');
    
    const obj1 = { a: 1, b: [2, 3] };
    const obj2 = { a: 1, b: [2, 3] };
    const obj3 = { a: 1, b: [2, 4] };
    
    console.log(equals(obj1, obj2)); // true
    console.log(equals(obj1, obj3)); // false
    
How to Choose: deep-eql vs deep-equal vs fast-equals
  • deep-eql:

    Choose deep-eql if you need a comprehensive solution that handles complex data structures, including circular references, and allows for custom equality functions. It is ideal for testing frameworks and scenarios where accuracy is paramount.

  • deep-equal:

    Choose deep-equal if you prefer a simple, lightweight library for deep equality checks without any dependencies. It is suitable for most use cases where performance is not the primary concern.

  • fast-equals:

    Choose fast-equals if you require a high-performance solution for comparing arrays and objects, especially in applications where speed is critical. It is optimized for performance while still providing accurate deep equality checks.

README for deep-eql

deep-eql

Improved deep equality testing for node and the browser.

build:? coverage:? dependencies:? devDependencies:?
Join the Slack chat Join the Gitter chat

What is Deep-Eql?

Deep Eql is a module which you can use to determine if two objects are "deeply" equal - that is, rather than having referential equality (a === b), this module checks an object's keys recursively, until it finds primitives to check for referential equality. For more on equality in JavaScript, read the comparison operators article on mdn.

As an example, take the following:

1 === 1 // These are primitives, they hold the same reference - they are strictly equal
1 == '1' // These are two different primitives, through type coercion they hold the same value - they are loosely equal
{ a: 1 } !== { a: 1 } // These are two different objects, they hold different references and so are not strictly equal - even though they hold the same values inside
{ a: 1 } != { a: 1 } // They have the same type, meaning loose equality performs the same check as strict equality - they are still not equal.

var deepEql = require("deep-eql");
deepEql({ a: 1 }, { a: 1 }) === true // deepEql can determine that they share the same keys and those keys share the same values, therefore they are deeply equal!

Installation

Node.js

deep-eql is available on npm.

$ npm install deep-eql

Usage

The primary export of deep-eql is function that can be given two objects to compare. It will always return a boolean which can be used to determine if two objects are deeply equal.

Rules

  • Strict equality for non-traversable nodes according to Object.is:
    • eql(NaN, NaN).should.be.true;
    • eql(-0, +0).should.be.false;
  • All own and inherited enumerable properties are considered:
    • eql(Object.create({ foo: { a: 1 } }), Object.create({ foo: { a: 1 } })).should.be.true;
    • eql(Object.create({ foo: { a: 1 } }), Object.create({ foo: { a: 2 } })).should.be.false;
  • When comparing Error objects, only name, message, and code properties are considered, regardless of enumerability:
    • eql(Error('foo'), Error('foo')).should.be.true;
    • eql(Error('foo'), Error('bar')).should.be.false;
    • eql(Error('foo'), TypeError('foo')).should.be.false;
    • eql(Object.assign(Error('foo'), { code: 42 }), Object.assign(Error('foo'), { code: 42 })).should.be.true;
    • eql(Object.assign(Error('foo'), { code: 42 }), Object.assign(Error('foo'), { code: 13 })).should.be.false;
    • eql(Object.assign(Error('foo'), { otherProp: 42 }), Object.assign(Error('foo'), { otherProp: 13 })).should.be.true;
  • Arguments are not Arrays:
    • eql([], arguments).should.be.false;
    • eql([], Array.prototype.slice.call(arguments)).should.be.true;