一行生成绝对唯一ID
生成唯一ID
唯一 ID 的核心要求是“全局不重复”,但前端环境的特殊性(无状态、多标签页、高并发操作),让很多看似合理的方案在实际场景中失效。
误区 1:时间戳 + 随机数(Date.now() + Math.random())
很多开发者会直觉性地将 “时间唯一性” 和 “随机唯一性” 结合,写出这样的代码:
// 错误示例:看似合理的“伪唯一”方案
function generateNaiveId() {
// 时间戳转36进制(缩短长度)+ 随机数截取
return Date.now().toString(36) + Math.random().toString(36).substr(2);
}
// 示例输出:l6n7f4v2am50k9m7o4
这种方案的缺陷在高并发场景下会暴露无遗:
时间戳精度不足:
Date.now()的精度是毫秒级(1ms),如果同一毫秒内调用多次(比如循环生成、高频接口回调),ID 的 “时间部分” 会完全重复;伪随机性风险:
Math.random()生成的是 “非加密级随机数”,其算法可预测,在短时间内可能生成重复的序列,进一步增加冲突概率。
结论:仅适用于低频次、非核心场景(如临时展示用 ID),绝对不能用于生产环境的核心数据标识。
误区 2:全局自增计数器
// 错误示例:自增计数器方案
let counter = 0;
function generateIncrementId() {
return `id-${counter++}`;
}
// 示例输出:id-0、id-1、id-2...
但在浏览器环境中,这个方案的缺陷更致命:
无状态丢失:页面刷新、路由跳转后,
counter会重置为 0,之前的 ID 序列会重复;多标签页冲突:用户打开多个相同页面时,每个页面的
counter都是独立的,会生成完全相同的 ID(比如两个页面同时生成id-0)。
结论:浏览器环境中几乎毫无实用价值,仅能用于单次会话、单页面的临时标识。
一行代码实现绝对唯一 —— crypto.randomUUID()
既然简单方案不可靠,我们需要借助浏览器原生提供的“加密级”能力。crypto.randomUUID()就是 W3C 标准推荐的官方解决方案,彻底解决 “唯一 ID” 难题。
crypto是浏览器内置的全局对象(无需引入任何库),专门提供加密相关能力,randomUUID()方法可直接生成符合RFC 4122 v4 规范的 UUID(通用唯一标识符):// 正确示例:生成绝对唯一ID
const uniqueId = crypto.randomUUID();
// 示例输出:3a6c4b2a-4c26-4d0f-a4b7-3b1a2b3c4d5e
crypto.randomUUID()的可靠性源于三个核心优势:
极低碰撞概率:v4 UUID 由 122 位随机数构成,组合数量高达
2^122(约 5.3×10^36),相当于 “在地球所有沙滩的沙粒中,选中某一颗特定沙粒” 的概率,实际场景中碰撞概率趋近于 0;加密级随机性:基于 “密码学安全伪随机数生成器(CSPRNG)”,随机性远优于
Math.random(),无法被预测或破解,避免恶意伪造重复 ID;跨环境兼容:生成的 UUID 是全球通用标准格式(8-4-4-4-12 位字符),前端、后端(Node.js、Java 等)、数据库(MySQL、MongoDB)都能直接识别,无需格式转换。
兼容性:覆盖所有现代环境
crypto.randomUUID()的支持范围已经非常广泛,完全满足绝大多数新项目需求:
浏览器:Chrome 92+、Firefox 90+、Safari 15.4+(2022 年及以后发布的版本);
服务器:Node.js 14.17+(LTS 版本均支持);
框架:Vue 3、React 18、Svelte 等现代框架无任何兼容性问题。
兼容性兜底方案(针对旧环境)
如果需要兼容旧浏览器(如 IE11)或低版本 Node.js,可以使用第三方库uuid(轻量、无依赖),其底层逻辑与crypto.randomUUID()一致:
npm install uuid
# 或 yarn add uuid
// 旧环境兜底方案
import { v4 as uuidv4 } from 'uuid';
const uniqueId = uuidv4();
// 示例输出:同标准UUID格式
目录