JavaScript生成随机数的核心是Math.random(),它返回[0,1)的浮点数;整数需用Math.floor缩放偏移,避免Math.round破坏均匀分布;密码学场景须用crypto API。
Math.random()
Math.random() 是唯一原生支持的随机数生成器,它返回一个大于等于 0、小于 1 的浮点数(即区间 [0, 1))。所有其他范围的随机数都得基于它做缩放和偏移——不是封装成函数就万事大吉,关键在边界处理是否严谨。
比如要生成 1 到 6 之间的随机整数(模拟掷骰子),错误写法是:Math.floor(Math.random() * 6) + 1 看似正确,但实际没问题;而真正危险的是:Math.round(Math.random() * 5) + 1 ——它会让 1 和 6 出现概率只有其他数的一半。
Math.floor(Math.random() * (max - min + 1)) + min:适用于闭区间 [min, max] 的整数,最常用也最安全Math.ceil(Math.random() * (max - min + 1)) + min - 1:等价但可读性差,不推荐Math.round() 会破坏均匀分布,因为两端值只覆盖半个区间min 或 max 是变量,注意确保它们是整数,否则结果可能越界或非预期Math.random() 不够安全Math.random() 是伪随机,由引擎实现决定(V8 使用 xorshift128+),不可预测但可复现。它**不适合密码学场景**,比如生成 token、加密盐值或抽奖种子。
crypto.getRandomValues()(浏览器)或 crypto.randomBytes()(Node.js)const arr = new Uint32Array(1); crypto.getRandomValues(arr); const safeRand = arr[0] % 100;
crypto API 是异步设计的替代方案(如 crypto.subtle.generateKey),但对简单随机数属于杀鸡用牛刀,需注意 crypto.randomInt() 是 19+ 新增,旧版只能手动封装 randomBytes
Math.random() 会不会“更随机”?不会。连续调用不会提升随机性,反而可能因重复 seed(极罕见)或浮点精度叠加引入偏差。有人误以为 Math.random() * Math.random() “更乱”,其实它让结果更集中在 0 附近,分布严重偏斜。
seedrandom 库自定义 seed)比堆调用有用得多== 比较浮点中间值,或循环中意外复用了同一个 Math.random() 结果Math.random = () => 0.5(注意仅限测试环境)边界计算和用途区分才是难点,不是记不住公式。