如何用Memoization生成不重复随机数?解决HTML元素随机Key缓存问题
问题分析与解决方案
现有代码的问题
第一个函数的问题
你写的generateRandomKey函数,参数cache = []的默认值是每次调用函数时才会创建新数组——也就是说,如果你每次调用都不传cache参数(比如直接调用generateRandomKey()),那每次都会生成空数组,缓存自然留不住。就算手动传cache,每次调用还得自己管理这个数组,非常麻烦。
第二个memoization代码的问题
这段代码有两个核心问题:
- 语法错误:
if (cache.includes(key)缺少闭合的),直接运行会报错。 - 逻辑错误:
memoizedRandomKey(cache)返回的是一个新函数,而不是生成的key,调用时根本拿不到结果;而且闭包结构完全搞错了,没能真正把缓存封装在内部复用。
推荐方案:用闭包封装缓存
不用全局变量也能保住缓存,闭包是最合适的方案。把缓存放在外层函数的作用域里,内层函数负责生成key,这样缓存只会初始化一次,每次调用内层函数都会复用同一个缓存:
function createKeyGenerator() { const cache = []; // 单独抽出生成key的逻辑,方便后续修改 function generateRawKey() { // 改用更高精度的随机字符串,避免很快耗尽所有可能值 return Math.random().toString(36).slice(2, 10); } return function() { let key; do { key = generateRawKey(); } while (cache.includes(key)); cache.push(key); return key; }; } // 使用方式:先创建生成器,之后每次调用就能拿到不重复的key const getUniqueKey = createKeyGenerator(); console.log(getUniqueKey()); // 示例输出:"x7k2b9z4" console.log(getUniqueKey()); // 另一个不重复的key
这个方案的优势:
- 缓存
cache被封装在闭包里,不会污染全局作用域 - 每次调用
getUniqueKey()都会复用同一个缓存,不会丢失 - 生成key的逻辑可以单独修改,扩展性更好
你原有逻辑的漏洞
- key取值范围极小:
Math.random().toFixed(2)生成的是0.00到1.00之间的两位小数,总共只有101个可能的值。一旦生成过101次,后续调用会无限递归(所有可能的key都在缓存里了),直接导致栈溢出。 - 默认参数逻辑错误:第一个函数的
cache = []默认值,每次调用都会新建数组,完全起不到缓存作用。 - memoization结构错误:没有正确利用闭包保存缓存,反而每次调用都返回新函数,根本无法复用缓存。
额外建议
如果是给HTML元素用key,还有更简单的替代方案:
- 自增整数:维护一个计数器,每次调用加1,绝对不会重复,性能比随机值更好(不用检查缓存)
- UUID:用
crypto.randomUUID()(现代浏览器支持),直接生成唯一的UUID,不需要缓存,因为UUID重复的概率可以忽略不计
自增整数的实现示例:
function createIncrementalKeyGenerator(start = 0) { let counter = start; return function() { return counter++; }; } const getKey = createIncrementalKeyGenerator(); console.log(getKey()); // 0 console.log(getKey()); // 1
内容的提问来源于stack exchange,提问作者ElMoscaviador
相关产品推荐
相关产品推荐

