What is hash-it?
The hash-it npm package is a utility for creating unique hash values from JavaScript objects. It is particularly useful for creating hash keys for complex objects, ensuring that the same object will always produce the same hash value.
What are hash-it's main functionalities?
Hashing Objects
This feature allows you to generate a unique hash value for a given JavaScript object. The same object will always produce the same hash value, which is useful for caching or quick comparisons.
const { hash } = require('hash-it');
const obj = { a: 1, b: 2 };
const hashValue = hash(obj);
console.log(hashValue);
Hashing Arrays
This feature allows you to generate a unique hash value for an array. It ensures that the same array will always produce the same hash value, which can be useful for array comparisons or caching.
const { hash } = require('hash-it');
const arr = [1, 2, 3];
const hashValue = hash(arr);
console.log(hashValue);
Hashing Nested Structures
This feature allows you to generate a unique hash value for nested structures, including objects within objects and arrays within objects. It ensures consistency in hash values for complex data structures.
const { hash } = require('hash-it');
const nestedObj = { a: { b: 2 }, c: [1, 2, 3] };
const hashValue = hash(nestedObj);
console.log(hashValue);
Other packages similar to hash-it
object-hash
The object-hash package provides similar functionality to hash-it by generating unique hash values for JavaScript objects. It supports a variety of hashing algorithms and can handle complex nested structures. Compared to hash-it, object-hash offers more customization options for the hashing process.
hasha
The hasha package is a versatile hashing utility that supports multiple hashing algorithms like MD5, SHA-1, and SHA-256. While it is not specifically designed for hashing objects, it can be used to hash strings, buffers, and other data types. It is more general-purpose compared to hash-it.
crypto
The built-in Node.js crypto module provides a wide range of cryptographic functionalities, including hashing. While it is more complex and requires more setup to hash objects compared to hash-it, it offers extensive options for cryptographic operations and is highly customizable.
hashIt
Fast and consistent hashCode for any object type
Table of contents
Usage
import hashIt from 'hash-it';
const hashIt = require('hash-it').default;
const hashIt = window.hashIt;
console.log(hashIt({foo: 'bar'}));
console.log(hashIt(window, true));
Overview
hashIt
has a simple goal: provide a fast and consistent hashCode for any object type that is uniquely based on its values. This has a number of uses such as duplication prevention or fast equality comparisons.
Any object type?
Yes, any object type. Primitives, ES2015 classes like Symbol
, DOM elements (yes, you can even hash the window
object if you want). Any object type.
With no exceptions?
Well ... sadly, no, there are a few exceptions.
In each of these cases, no matter what the values of the object, they will always yield the same hash result, which is unique to each object type. If you have any ideas about how these can be uniquely hashed, I welcome them!
Here is the list of object classes that have been tested and shown to produce unique hashCodes:
Arguments
Array
ArrayBuffer
Boolean
DataView
Date
(based on valueOf
)Error
(based on message
)
- Includes all sub-types (e.g.
TypeError
, ReferenceError
, etc.)
Float32Array
Float64Array
Function
(based on toString
)GeneratorFunction
(based on toString
)Int8Array
Int16Array
Int32Array
HTMLElement
(based on tagName
, attributes
, and innerHTML
)
- Includes all sub-types (e.g.
HTMLAnchorElement
, HTMLDivElement
, etc.)
Map
Math
(based on E
, LN2
, LN10
, LOG2E
, LOG10E
, PI
, SQRT1_2
, and SQRT2
)Null
Number
Object
(can handle circular objects)Proxy
RegExp
Set
String
Symbol
Uint8Array
Uint8ClampedArray
Uint16Array
Uint32Array
Undefined
Window
This is basically all I could think of, but if I have missed an object class let me know and I will add it!
Utility functions
isEmpty
isEmpty(object: any): boolean
Determines if object is empty based on hashCode, with empty defined as:
- Empty array (
[]
) - Empty map (
new Map()
) - Empty number, or zero (
0
) - Empty object (
{}
) - Empty set (
new Set()
) - Empty string (
''
) - Undefined (
undefined
) - Null (
null
)
This differs from the implementation by lodash
, where a value is considered not empty if an Array
, Object
, Map
, or Set
. Think of this definition of empty as "having no value(s)".
isEqual
isEqual(object1: any, object2: any[, object3: any[, ...objectN]]): boolean
Compares all objects passed to it to determine if they are equal to one another based on hashCode
const foo = {
foo: 'bar'
};
const alsoFoo = {
foo: 'bar'
};
console.log(foo === alsoFoo);
console.log(hashIt.isEqual(foo, alsoFoo));
isNull
isNull(object: any): boolean
Determines if object is null based on hashCode
isUndefined
isUndefined(object: any): boolean
Determines if object is undefined based on hashCode
Gotchas
While the hashes will be consistent when calculated within the same browser environment, there is no guarantee that the hashCode will be the same across different browsers due to browser-specific implementations of features. A vast majority of the time things line up, but there are some edge cases that can cause differences, so just something to be mindful of.
Browser support
- Chrome (all versions)
- Firefox (all versions)
- Edge (all versions)
- Opera 15+
- IE 9+
- Safari 6+
- iOS 8+
- Android 4+
Node support
Development
Standard stuff, clone the repo and npm install
dependencies. The npm scripts available:
build
=> run webpack to build development dist
file with NODE_ENV=developmentbuild:minified
=> run webpack to build production dist
file with NODE_ENV=productiondev
=> run webpack dev server to run example app / playgrounddist
=> runs build
and build:minified
lint
=> run ESLint against all files in the src
folderprepublish
=> runs prepublish:compile
when publishingprepublish:compile
=> run lint
, test:coverage
, transpile:es
, transpile:lib
, dist
test
=> run AVA test functions with NODE_ENV=test
test:coverage
=> run test
but with nyc
for coverage checkertest:watch
=> run test
, but with persistent watchertranspile:lib
=> run babel against all files in src
to create files in lib
transpile:es
=> run babel against all files in src
to create files in es
, preserving ES2015 modules (for
pkg.module
)