-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
70 lines (61 loc) · 1.49 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
class Hasher extends Uint32Array {
constructor() {
super(1);
this[0] = 5381;
}
push = (str) => {
let i = str.length;
while (i--) {
this[0] = (this[0] * 33) ^ (str.charCodeAt(i) & 0xffff);
}
}
}
/**
* @param {any} value
* @returns {number}
*/
export default function hash(value) {
const hasher = new Hasher();
hasher.push(route(value, hasher.push));
return hasher[0];
}
function route(value, push, refs) {
switch (typeof value) {
case 'string':
push(value);
return 's';
case 'symbol':
push(value.description);
return 'm';
case 'object':
hashObject(value, push, refs || []);
return 'o';
case 'undefined':
return '';
case 'number':
push(value.toString());
return 'n';
case 'boolean':
push(value.toString());
return 'b';
case 'bigint':
push(value.toString());
return 'g';
case 'function':
push(value.toString());
return 'f';
}
}
function hashObject(target, push, refs) {
if (target === null)
return push('null');
if (refs.includes(target))
return push('&');
if (target instanceof Date)
return push(target.toISOString());
refs.push(target);
for (const key in target) {
push(key);
push(route(target[key], push, refs));
}
}