Math.random 能做什么
js 里最常用的随机数来源是 Math.random(),它返回 [0, 1) 区间的浮点数,包含 0 但不包含 1。注意两点:它不接受参数,也无法设定种子,因此结果不可复现;不同浏览器引擎的实现细节并不一致,不适合做需要严格可验证的随机抽样。
Math.random(); // 例如 0.7234…
生成指定区间的随机数
最直接的写法是把 Math.random() 的区间映射过去:
// 浮点数,范围 [min, max)
const rand = (min, max) => Math.random() * (max – min) + min;
需要整数时用 Math.floor,闭区间 [min, max] 的写法是:
const randInt = (min, max) =>
Math.floor(Math.random() * (max – min + 1)) + min;
数组随机取值可以直接用这个整数做下标,洗牌则用 Fisher-Yates 算法,从后往前交换,保证每种排列概率相同:
const shuffle = arr => {
for (let i = arr.length – 1; i > 0; i–) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
};
常见坑:取整方式与区间边界
用 Math.round 生成整数会出问题。Math.round(Math.random() * n) 中 0 和 n 只在极窄区间被命中,两端概率约为中间值的一半。整数随机一律用 Math.floor。
另一个细节是 max - min + 1。漏掉 +1 会让最大值永远取不到,写闭区间函数时最容易出错。封装成工具函数并加测试,比每次手写更稳。
需要安全随机时用什么
Math.random() 是伪随机,不适用于验证码、抽奖签名、令牌等场景。浏览器提供 crypto.getRandomValues() 生成密码学安全的随机值;Node.js 可用 crypto.randomInt() 直接拿到区间整数。生成 0 到 255 的随机字节示例:
const buf = new Uint8Array(1);
crypto.getRandomValues(buf);
若要在安全随机下取区间整数,可用拒绝采样避免取模偏差:先按区间范围取随机值,超出可整除范围就重取,而不是简单 %。这在抽奖、发券等对公平性敏感的场景值得多写几行。
可复现的随机:带种子的实现
做动画、测试、数据模拟时常常需要固定随机序列。实现思路是自己维护一个简单伪随机函数,例如 mulberry32,把种子作为状态传入,每次调用返回 [0, 1)。这样同一种子必然产生同一序列,便于回归测试和问题复现。生产环境不要用它替代安全随机。
选型建议
普通交互、动画抖动、占位数据用 Math.random() 足够;涉及金额、身份、权限、抽奖结果时切换到 crypto 接口;需要可复现行为时用带种子的自定义实现。先明确随机数的用途,再决定用哪一种,比随手写 Math.random() 更可靠。