js 随机数(超详细)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
- 《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
在 JavaScript 开发中,"js 随机数" 是一个高频需求,无论是游戏中的道具掉落、抽奖系统的实现,还是数据测试时的模拟生成,都离不开随机数的支撑。然而,许多开发者在初次接触这一主题时,常因对随机数生成机制的误解而陷入困境。本文将从基础到进阶,系统性地解析如何在 JavaScript 中高效、安全地生成随机数,并通过实际案例展示其应用场景。
一、基础:Math.random() 的核心原理
JavaScript 的随机数生成主要依赖于全局对象 Math
中的 Math.random()
方法。该方法返回一个 [0, 1) 区间的浮点数,即包含 0 但不包含 1。
1.1 方法特性与局限性
- 伪随机性:
Math.random()
生成的数是伪随机的,其“随机性”基于算法和初始种子值(seed)。这意味着在相同种子下,同一代码段会生成相同的序列。 - 均匀分布:理论上,该方法在区间内均匀分布,但实际实现可能因 JavaScript 引擎的差异而存在细微偏差。
示例代码
// 生成 0 到 1 之间的随机浮点数
const randomValue = Math.random();
console.log(randomValue); // 可能输出:0.123456789
二、核心技巧:生成指定范围的随机数
多数场景需要的随机数并非 [0,1),而是整数或特定区间的数值。以下是常见转换方法:
2.1 生成随机整数
方法 1:乘法 + 取整
通过 Math.random()
乘以范围长度,再用 Math.floor()
或 Math.ceil()
去除小数部分。
- 区间 [min, max) 的随机整数:
function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min)) + min; } // 例如生成 1 到 10 的整数: const result = getRandomInt(1, 10); // 可能输出 3
- 区间 [min, max] 的随机整数:
需要将max
替换为max + 1
:const result = Math.floor(Math.random() * (max - min + 1)) + min;
方法 2:ES6 的 Math.trunc()
function getRandomIntES6(min, max) {
return Math.trunc(Math.random() * (max - min)) + min;
}
形象比喻
想象将 [0,1) 的区间比作一条长度为 1 的线段,乘以 (max - min)
相当于将线段“拉伸”到目标长度,而取整操作则是“切割”线段后取整数部分。
2.2 生成随机浮点数
若需保留小数位,可通过 toFixed()
方法控制精度:
function getRandomFloat(min, max, decimalPlaces = 2) {
const value = Math.random() * (max - min) + min;
return parseFloat(value.toFixed(decimalPlaces));
}
// 生成 1.5 到 3.5 之间的两位小数:
const result = getRandomFloat(1.5, 3.5); // 可能输出 2.76
三、进阶问题与解决方案
3.1 随机数重复与去重
在需要唯一值的场景(如抽奖、验证码),直接使用 Math.random()
可能导致重复。此时可通过以下方法解决:
方法 1:数组去重法
function generateUniqueNumbers(count, min, max) {
const numbers = [];
while (numbers.length < count) {
const num = getRandomInt(min, max);
if (!numbers.includes(num)) {
numbers.push(num);
}
}
return numbers;
}
// 生成 5 个不重复的 1-10 整数:
const uniqueNumbers = generateUniqueNumbers(5, 1, 10);
方法 2:Fisher-Yates 洗牌算法
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
// 生成 1-10 的随机排列:
const shuffled = shuffle([...Array(10).keys()].map(i => i + 1));
3.2 加密安全的随机数
Math.random()
不适合加密场景,因其伪随机性易被预测。此时可使用 Web Crypto API:
async function getSecureRandomInt(min, max) {
const array = new Uint32Array(1);
await crypto.subtle.randomFill(array);
return (array[0] % (max - min)) + min;
}
// 生成加密安全的 1-100 整数:
getSecureRandomInt(1, 100).then(result => console.log(result));
四、实际案例与应用
4.1 抽奖系统
const participants = ["Alice", "Bob", "Charlie", "David"];
function drawWinner() {
const index = Math.floor(Math.random() * participants.length);
return participants[index];
}
console.log("Winner is:", drawWinner()); // 可能输出 "Charlie"
4.2 简易验证码生成
function generateVerificationCode(length = 6) {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let code = "";
for (let i = 0; i < length; i++) {
const index = Math.floor(Math.random() * chars.length);
code += chars[index];
}
return code;
}
console.log("Verification Code:", generateVerificationCode(6)); // 可能输出 "aB7xK3"
五、性能优化与最佳实践
5.1 避免频繁调用 Math.random()
若需生成大量随机数,可预先生成一个数组再复用:
function generateBatchRandoms(count) {
const arr = new Array(count);
for (let i = 0; i < count; i++) {
arr[i] = Math.random();
}
return arr;
}
5.2 种子随机数生成(需第三方库)
若需可复现的随机序列,可借助 seedrandom
库:
const { createSeededRNG } = require("seedrandom");
const rng = createSeededRNG("my-seed");
console.log(rng()); // 始终返回相同值
六、结论
掌握 "js 随机数" 的核心方法与进阶技巧,能显著提升开发效率。从基础的 Math.random()
到加密安全的 Web Crypto API,开发者需根据场景选择合适方案。通过本文的案例与代码示例,读者可快速实现抽奖系统、验证码生成等需求,并理解随机数背后的数学逻辑。未来随着 JavaScript 的发展,随机数生成技术将持续演进,开发者需持续关注其最佳实践与性能优化策略。