stable-hash
A tiny and fast (481b unpkg) lib for "stably hashing" a JavaScript value. Originally created for SWR.
It's similar to JSON.stringify(value), but:
1. Supports any JavaScript value (BigInt, NaN, Symbol, function, class, ...)
2. Sorts object keys (stable)
3. Supports circular objects
Use
Examples
Primitive Value
BigInt:
Symbol:
hash(Symbol.for('foo')) === hash(Symbol.for('foo'))
hash(Symbol.for('foo')) === hash(Symbol('foo'))
hash(Symbol('foo')) === hash(Symbol('foo'))
hash(Symbol('foo')) !== hash(Symbol('bar'))
Since Symbols cannot be serialized, stable-hash simply uses its description as the hash.
Regex
Date
Array
Circular:
Object
hash({ foo: 'bar' }) === hash({ foo: 'bar' })
hash({ foo: { bar: 1 } }) === hash({ foo: { bar: 1 } })
Stable:
Circular:
Function, Class, Set, Map, Buffer...
stable-hash guarantees reference consistency (===) for objects that the constructor isn't Object.
Notes
This function does something similar to JSON.stringify, but more than it. It doesn't generate a secure checksum, which usually has a fixed length and is hard to be reversed. With stable-hash it's still possible to get the original data. Also, the output might include any charaters, not just alphabets and numbers like other hash algorithms. So:
- Use another encoding layer on top of it if you want to display the output.
- Use another crypto layer on top of it if you want to have a secure and fixed length hash.
import crypto from 'crypto'
import hash from 'stable-hash'
const weakHash = hash(anyJavaScriptValueHere)
const encodedHash = Buffer.from(weakHash).toString('base64')
const safeHash = crypto.createHash('MD5').update(weakHash).digest('hex')
Also, the consistency of this lib is sometimes guaranteed by the singularity of the WeakMap instance. So it might not generate the consistent results when running in different runtimes, e.g. server/client or parent/worker scenarios.
License
Created by Shu Ding. Released under the MIT License.