1

我不确定这个问题的标题是最好的,但希望这个解释能很好地说明我想要做什么。现在是凌晨 4 点,所以请原谅我向您传达的困惑。

基本上我想做的是确定用户选择的元素是否再次出现在网站的任何页面上。这用于实现“不再向我显示”通知,而无需在服务器端维护用户隐藏什么通知的巨大数据库,并且还允许创建动态生成的通知。

手动为每个通知赋予唯一标识符会使动态通知变得不可能,因此需要动态解决方案。

我的想法是生成通知的散列,使用简单的方法将通知的文本转换为整洁的小散列,如果使用大量通知,可以有效地存储在localStorage不占用大量内存的情况下(或者如果这些通知包含大量文本)。

显然,像 MD5 和 SHA-1 这样的东西是直接的候选者,因为它们被广泛使用,并且在 JavaScript 中有许多示例实现来弥补这些函数不是原生的事实。

但对我来说,它们似乎有点矫枉过正。我见过的每个实现都定义了至少十几个帮助函数来完成工作,而且我不喜欢使用我不理解的代码。此外,我不需要加密强度,我只需要一个快速简单的哈希。

我想出了以下几点:

function hash(str) {
    var l = str.length, i, out = 0;
    for( i=0; i<l; i++) out = (out<<1)^str.charCodeAt(i);
    return out;
}

在使用少量值进行一些测试后,这似乎生成了相当不错的哈希值。这显然是一致的:相同的输入将产生相同的输出。

我真正想知道的是:这是一个可用的哈希函数吗?我的意思是,使用这个哈希函数是否有很高的冲突风险?


指出<<不循环,仅移位丢弃溢出后,函数为:

function hash(str) {
    var l = str.length, i, out = 0;
    for( i=0; i<l; i++) out = ((out<<1)|(out&0x80000000?1:0))^str.charCodeAt(i);
    return out;
}

这基本上实现了位旋转,因为我认为没有内置的运算符。

4

1 回答 1

1

我测试了几个样本,结果似乎不是很好,因为长度超过 32 个字符且具有相同结尾的字符串给出了相同的结果。

console.log(hash('Hello world. Lorem ipsum dolor sit amet, consectetur adipiscing elit.'));
console.log(hash('Something entirely different. Lorem ipsum dolor sit amet, consectetur adipiscing elit.'));

对我来说,这721528210两种情况都会产生。

我认为这是因为您通过使用 << 移动字节来不断破坏字节,同时 XOR ^ 是成对的。任何字母都会改变当前的 32 个字节,但这些都将在 32 个字符后被销毁。

于 2012-05-25T08:58:49.243 回答