A tiny (304B to 489B) utility to check for deep equality

Related tags

API dequal
Overview

dequal CI

A tiny (304B to 489B) utility to check for deep equality

This module supports comparison of all types, including Function, RegExp, Date, Set, Map, TypedArrays, DataView, null, undefined, and NaN values. Complex values (eg, Objects, Arrays, Sets, Maps, etc) are traversed recursively.

Important:

  • key order within Objects does not matter
  • value order within Arrays does matter
  • values within Sets and Maps use value equality
  • keys within Maps use value equality

Install

$ npm install --save dequal

Modes

There are two "versions" of dequal available:

dequal

Size (gzip): 489 bytes
Availability: CommonJS, ES Module, UMD

dequal/lite

Size (gzip): 304 bytes
Availability: CommonJS, ES Module

IE9+ Number String Date RegExp Object Array Class Set Map ArrayBuffer TypedArray DataView
dequal
dequal/lite 👍

Note: Table scrolls horizontally!

Usage

import { dequal } from 'dequal';

dequal(1, 1); //=> true
dequal({}, {}); //=> true
dequal('foo', 'foo'); //=> true
dequal([1, 2, 3], [1, 2, 3]); //=> true
dequal(dequal, dequal); //=> true
dequal(/foo/, /foo/); //=> true
dequal(null, null); //=> true
dequal(NaN, NaN); //=> true
dequal([], []); //=> true
dequal(
  [{ a:1 }, [{ b:{ c:[1] } }]],
  [{ a:1 }, [{ b:{ c:[1] } }]]
); //=> true

dequal(1, '1'); //=> false
dequal(null, undefined); //=> false
dequal({ a:1, b:[2,3] }, { a:1, b:[2,5] }); //=> false
dequal(/foo/i, /bar/g); //=> false

API

dequal(foo, bar)

Returns: Boolean

Both foo and bar can be of any type.
A Boolean is returned indicating if the two were deeply equal.

Benchmarks

Running Node v10.13.0

The benchmarks can be found in the /bench directory. They are separated into two categories:

  • basic – compares an object comprised of String, Number, Date, Array, and Object values.
  • complex – like basic, but adds RegExp, Map, Set, and Uint8Array values.

Note: Only candidates that pass validation step(s) are listed.
For example, fast-deep-equal/es6 handles Set and Map values, but uses referential equality while those listed use value equality.

Load times:
  assert             0.109ms
  util               0.006ms
  fast-deep-equal    0.479ms
  lodash/isequal    22.826ms
  nano-equal         0.417ms
  dequal             0.396ms
  dequal/lite        0.264ms

Benchmark :: basic
  assert.deepStrictEqual  x    325,262 ops/sec ±0.57% (94 runs sampled)
  util.isDeepStrictEqual  x    318,812 ops/sec ±0.87% (94 runs sampled)
  fast-deep-equal         x  1,332,393 ops/sec ±0.36% (93 runs sampled)
  lodash.isEqual          x    269,129 ops/sec ±0.59% (95 runs sampled)
  nano-equal              x  1,122,053 ops/sec ±0.36% (96 runs sampled)
  dequal/lite             x  1,700,972 ops/sec ±0.31% (94 runs sampled)
  dequal                  x  1,698,972 ops/sec ±0.63% (97 runs sampled)

Benchmark :: complex
  assert.deepStrictEqual  x    124,518 ops/sec ±0.64% (96 runs sampled)
  util.isDeepStrictEqual  x    125,113 ops/sec ±0.24% (96 runs sampled)
  lodash.isEqual          x     58,677 ops/sec ±0.49% (96 runs sampled)
  dequal                  x    345,386 ops/sec ±0.27% (96 runs sampled)

License

MIT © Luke Edwards

Comments
  • dequal is not a function

    dequal is not a function

    Just some super basic usage, getting an error saying that dequal isn't a function since the update to 2.0

    import dequal from 'dequal'

    function useDeepCompareMemoize(value) {
      const ref = React.useRef()
    
      if (!dequal(value, ref.current)) {
        ref.current = value
      }
    
      return ref.current
    }
    
    opened by stolinski 7
  • Specify type definitions for tsc node12 imports

    Specify type definitions for tsc node12 imports

    In tsc nightly a new module resolutions scheme is introduced called node12 or nodenext which uses this "exports" field in package.json files. When this is present and being used then the old root "types" is not used. You have to specify the types in the specific exports (when the files are not adjacent).

    opened by willstott101 5
  • Map and Set Code

    Map and Set Code

    Here is the code to support Map and Set conventionalized for older browsers (which may not be necessary depending on what you are doing for transpile). I have this locally along with unit test additions. I can do a pull request, you can add to your code, or (of course) you can ignore:

    if(typeof(Map)==="function" && ctor === Map) {
    			if(foo.size === bar.size) {
    				for(const [key,value] of foo.entries()) { // Maps are mathematically unordered
    					if(!dequal(bar.get(key),value)) { // so ... simple existence of same key value is good enough
    						return false;
    					}
    				}
    				return true;
    			}
    			return false;
    		}
    		
    		if(typeof(Set)==="function" && ctor === Set) {
    			if(foo.size === bar.size) {
    				for(const fvalue of foo.entries()) { // Sets are mathematically unordered
    					let found;
    					for(const bvalue of bar.entries()) { // so ... need to compare each entry
    						if(found = dequal(fvalue,bvalue)) {
    							break;
    						}
    					}
    					if(!found) {
    						return false;
    					}
    				}
    				return true;
    			}
    			return false;
    		}
    
    opened by anywhichway 5
  • Doesn't compare Sets

    Doesn't compare Sets

    Hi!

    I just noticed this library does not compare Sets correctly.

    Repro:

    
    var dequal = require("dequal")
    
    let a = new Set([1,2,3,4])
    let b = new Set([1,2,3,4])
    
    console.log(dequal(a,b))
    

    https://runkit.com/embed/yiu9lr2kont0

    As an example, lodash's isEqual does compare Sets and in the above use case does return true.

    This is also related to https://github.com/kentcdodds/use-deep-compare-effect/issues/15

    Fran

    opened by franleplant 5
  • Minor suggestion -- add

    Minor suggestion -- add "strict" option for "loose" equality

    Great library, thanks ! 👍

    One small suggestion -- it's be nice if we could select between "loose" or "strict" equality checking. Currently, dequal(1, true) returns false, which is correct if we're checking 1 === true, but not for 1 == true. Similar for dequal(null, undefined).

    Any chance of making the type of equality check configurable?

    opened by CarlosNZ 3
  • Array Comparison

    Array Comparison

    There may be cases when your Array comparison breaks. Although not necessarily a good coding approach, sometimes non-numeric values are added to Arrays by programmers for book-keeping (The "arrays" in the DOM, e.g. attributes, are kind of like this). If you simply delete the Array section of your code, the unit tests still pass since arrays are just regular objects that only have numeric keys by default plus a length property and some extra functions. Also your code will be slightly smaller while also addressing this edge case.

    opened by anywhichway 3
  • Extend to compare non-bare objects

    Extend to compare non-bare objects

    Thanks for the great projejct @lukeed! Discovered this while porting a project of mine from tape to uvu (this was the only blocker):

    class Foo {}
    
    const a = new Foo();
    const b = new Foo();
    
    dequal(a, b); // false :(
    

    I guess this would be fixed by replacing the ctor === Object check with typeof foo === 'object'. Was this an issue with performance? Comparing class instances and other non-basic objects is indispensable when writing unit tests.

    Related: #2

    opened by mourner 3
  • bundt

    bundt

    Although bundt is a devDependency it does not run on Debian after a regular npm install. Should it?

    npm run bundt
    npm ERR! missing script: bundt
    
    npm ERR! A complete log of this run can be found in:
    npm ERR!     /home/syblackwell/.npm/_logs/2020-07-17T23_56_51_497Z-debug.log
    
    ls node_modules
    buffer-from  dequal  kleur    rewrite-imports  source-map-support  uvu
    bundt        diff    mk-dirs  sade             terser
    commander    esm     mri      source-map       totalist
    
    opened by anywhichway 2
  • Fails when comparing Invalid Dates

    Fails when comparing Invalid Dates

    I tried to use dequal as lodash.isEqual replacement, but find out that when comparing two Invalid Dates dequal returns true.

    Not sure if this is correct, because of possible false possitives - new Date('foo') is not same as new Date('bar'). Solution - instead of comparing date.getTime(), isNaN(date) should be considered.

    Again, not sure what result to expect here plus changing this will cause BREAKING-CHANGE.

    I'll stick with lodash's isEqual for now :(

    opened by wysher 1
  • Fails when comparing Invalid Date

    Fails when comparing Invalid Date

    I tried to use dequal as lodash.isEqual replacement, but find out that when comparing two Invalid Dates dequal returns true.

    Not sure if this is correct, because of possible false possitives - new Date('foo') is not same as new Date('bar'). Solution - instead of comparing date.getTime(), isNaN(date) should be considered.

    Again, not sure what result to expect here plus changing this will cause BREAKING-CHANGE.

    I'll stick with lodash's isEqual for now :(

    opened by wysher 1
  • Fix .d.ts

    Fix .d.ts

    Module declaration did not work because index.d.ts is not a rootType, so I created a declaration file for each mode.

    Same as https://github.com/lukeed/klona/pull/22

    opened by tripodsgames 1
  • Doesn't work with URLSearchParams

    Doesn't work with URLSearchParams

    See https://stackblitz.com/edit/js-gxcyih?file=index.js

    I think it's because of the way we fall into the "plain" object comparison in https://github.com/lukeed/dequal/blob/master/src/index.js#L73-L80

    const x = new URLSearchParams();
    x.append("foo", "bar");
    
    for (i in x) {
      if (x.hasOwnProperty(i)) console.info(i);
    }
    

    => Nothing gets printed because e.g. entries is always the same, but the stuff returned from entries is not.

    opened by defaude 0
  • fix: prevent comparisons beyond typed array bounds

    fix: prevent comparisons beyond typed array bounds

    Reverse iteration over TypedArrays was starting at foo.byteLength - 1, not foo.length - 1. For TypedArrays with .BYTES_PER_ELEMENT greater than 1, that was resulting in up to 7*foo.length needless pairs of out-of-bounds array accesses and undefined === undefined comparisons.

    opened by EvanWard97 0
  • Infinite loop when both arguments have cycles

    Infinite loop when both arguments have cycles

    If both arguments have cycles, like if you're trying to compare doubly-linked lists, dequal goes into an infinite loop.

    repro:

    const a: any = {}, b: any = {};
    a.next = b;
    b.previous = a;
    
    const c: any = {}, d: any = {};
    c.next = d;
    d.previous = c;
    
    dequal(a, c);
    
    opened by justinfagnani 10
  • Fails to correctly compare objects created by constructors from another realm (like iframes)

    Fails to correctly compare objects created by constructors from another realm (like iframes)

    This is definitely an edge-case, but when comparing objects like Array across iframe boundaries, instanceof will not work. See MDN's example of this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray#instanceof_vs_isArray

    opened by NickGard 1
Releases(v2.0.3)
  • v2.0.3(Jul 11, 2022)

    Patches

    • Add "types" conditions for TypeScript's "nodenext" resolver (#20): f99ec70 Thank you @willstott101~!

    Full Changelog: https://github.com/lukeed/dequal/compare/v2.0.2...v2.0.3

    Source code(tar.gz)
    Source code(zip)
  • v2.0.2(Aug 19, 2020)

  • v2.0.1(Aug 17, 2020)

    Patches

    • (types): Alter index.d.ts so that entry "mode" entry maintains type definition: 90f5eb9

    Chores

    • (docs) Fix outdated import statement in README example (#13): f8443f5
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Aug 12, 2020)

    Breaking

    • Migrated from default to named export: 88f7ec5

      ESM/TypeScript

      - import dequal from 'dequal';
      + import { dequal } from 'dequal';
      

      CommonJS

      - const dequal = require('dequal');
      + const { dequal } = require('dequal');
      
    • Dropped Internet Explorer support If IE9+ support is still needed, please use the new dequal/lite entry (see below). The dequal/lite code is identical to [email protected].

    Features

    • Added ArrayBuffer and TypeArray support to dequal entry: cf14422

    • Added Map and Set support to dequal entry: ef34745, 0f081ab Set values, Map values, and Map keys use deep value equality.

      Example

      const foo = new Map([
        [{ abc: 123 }, 'value']
      ]);
      
      const bar = new Map([
        [{ abc: 123 }, 'value']
      ]);
      

      With referential equality, foo and bar are not equal. Even though they look identical, their { abc: 123 } key is not a shared reference. However, with value equality, foo and bar are equal. This is because their { abc: 123 } key holds the same value –– this follows how dequal and dequal/lite compare any other object.

    • Added native ESM support via exports mapping: 3533248 Allows for Node.js import statements to work within native ESM resolvers.

    • Added dequal/lite mode: 81075b1 Preserves [email protected] behaviors, allowing opt-in, continued IE support. Unlike the primary dequal offering, this mode does not & will not support Maps, Sets, TypedArray, etc.

    Chores

    • (readme): Add documentation for "modes" with table comparison: 00c7428..f5210c6, 92e9c7e
    • (action) Update CI config (paths, branches, ignores): 0b3e650, 154af6f, 35192d7
    • (bench) Update lodash version (#10): a255871
    • (bench) Refactor and update bench runner for multiple fixtures: 901deab, 8b14a8a
    • (bench) Update benchmark results: b971b41
    • (tests) Update uvu version: b3cfc11
    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(Jul 15, 2020)

    Patches

    • Support Object dictionaries: c8b3ace
    • Support custom Objects/Classes (#4, #5): 7d090f4
    • Do not use matching length for Array precondition: 4d76378

    Chores

    • Attach GitHub Action for CI: badbbaa
    • Include own benchmark suite: fd3d291, b380948
    • Update module size: 451ad74, 1fbdd48
    • Update test runner: 96e0cb9, d8d0904
    • Add additional test suites: 2dc8be3, c8b3ace, 868adcd, 45c6194
    • Update devDependencies: d4c815c
    Source code(tar.gz)
    Source code(zip)
Owner
Luke Edwards
Luke Edwards
A tiny JavaScript utility to access deep properties using a path (for Node and the Browser)

object-path Access deep properties using a path Changelog 0.11.5 SECURITY FIX. Fix a prototype pollution vulnerability in the set() function when usin

Mario Casciaro 1k Dec 29, 2022
Check in, check the weather, Check out.

☀️ Just-Weather ??️ Hi, Welcome! Just Weather is a Web App designed for Fast Real-Time Weather queries in combination with well Thought Out Visual Des

Miguel Ángel 6 Aug 7, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
An isomorphic and configurable javascript utility for objects deep cloning that supports circular references.

omniclone An isomorphic and configurable javascript function for object deep cloning. omniclone(source [, config, [, visitor]]); Example: const obj =

Andrea Simone Costa 184 May 5, 2022
Check ipo allotment result from CLI. [WIP for bulk check]

# Check your ipo allotment result via CLI Install node js and run these commands > clone the repo > cd checkipo-cli > npm

Yaman Sarabariya 4 Oct 12, 2022
A mobile web application to check the data on the total covid19 confirmed cases and deaths, check data for all countries with recorded cases.

This is a mobile web application to check the data on the total covid19 confirmed cases and deaths, check data for all countries with recorded cases. It also has a details page to check for the statistics for each region/state if available.

Solomon Hagan 7 Jul 30, 2022
🦕. A type-check utility function to indicating that the code is unreachable

unreachable A type-check utility function to indicating that the code is unreachable. Usage For example, the following code passed type checking. impo

Alisue 6 Oct 2, 2022
Node JS utility to check the signature of Apple P12 Certificates.

CertCheck Node JS utility to check the signature of Apple P12 Certificates. Confirmed to work on macOS and Linux. Windows may need slight changes. Wor

Jailbreaks.app Team 10 Dec 24, 2022
A utility for creating toggleable items with JavaScript. Inspired by bootstrap's toggle utility. Implemented in vanillaJS in a functional style.

LUX TOGGLE Demo: https://jesschampion.github.io/lux-toggle/ A utility for creating toggleable dom elements with JavaScript. Inspired by bootstrap's to

Jess Champion 2 Oct 3, 2020
Deep Learning in Javascript. Train Convolutional Neural Networks (or ordinary ones) in your browser.

ConvNetJS ConvNetJS is a Javascript implementation of Neural networks, together with nice browser-based demos. It currently supports: Common Neural Ne

Andrej 10.4k Dec 31, 2022
A JavaScript deep learning and reinforcement learning library.

neurojs is a JavaScript framework for deep learning in the browser. It mainly focuses on reinforcement learning, but can be used for any neural networ

Jan 4.4k Jan 4, 2023
Deep Neural Network Sandbox for JavaScript.

Deep Neural Network Sandbox for Javascript Train a neural network with your data & save it's trained state! Demo • Installation • Getting started • Do

Matias Vazquez-Levi 420 Jan 4, 2023
Defacement detection with deep learning

In0ri is a defacement detection system utilizing a image-classification convolutional neural network. Introduction When monitoring a website, In0ri wi

Just4Fun Security 47 Nov 30, 2022
clubhouse + google deep voice + gpt3

Omega This repo is code for a machine learning social "turing" test run on Clubhouse. It's a conversational bot that leverages GPT-3 to reply contextu

Thomas Davis 37 Nov 17, 2022
Visualizer for neural network, deep learning, and machine learning models

Netron is a viewer for neural network, deep learning and machine learning models. Netron supports ONNX, TensorFlow Lite, Caffe, Keras, Darknet, Paddle

Lutz Roeder 21k Jan 5, 2023
Lightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Scala, Go, Javascript and more

Apache MXNet (incubating) for Deep Learning Apache MXNet is a deep learning framework designed for both efficiency and flexibility. It allows you to m

The Apache Software Foundation 20.2k Jan 5, 2023
Fast, deep, scalable object cloning for JavaScript

A new approach to deep cloning. A simple library with no external dependencies gives you the opportunity to customize the cloning strategy.

Egor Efimenko 3 Mar 10, 2022
A command-line tool to convert Project Zomboid map data into Deep Zoom format

pzmap2dzi pzmap2dzi is a command-line tool running on Windows to convert Project Zomboid map data into Deep Zoom format. Features Supports both python

Min Xiang 14 Dec 31, 2022