JavaScript 中如何生成 UUID
原生方法:crypto.randomUUID()
自 Node.js 14.17.0 和现代浏览器起,JavaScript 提供了内置的 UUID v4 生成方法,无需任何外部依赖。crypto.randomUUID() 使用加密安全的随机数生成器,直接返回符合 RFC 4122 格式的 UUID v4 字符串。这是目前推荐的首选方法,简单、安全、零依赖。在 Node.js 中需要从 crypto 模块导入;在浏览器环境中,globalThis.crypto.randomUUID() 可以直接使用。
// Node.js (v14.17.0+)
const { randomUUID } = require('crypto');
const id = randomUUID();
console.log(id); // e.g., '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
// ES Module 写法
import { randomUUID } from 'crypto';
// 浏览器端(现代浏览器)
const id = globalThis.crypto.randomUUID();
// async 函数中使用
async function createResource() {
const resourceId = crypto.randomUUID();
return { id: resourceId, createdAt: new Date() };
}
使用 uuid npm 包
uuid 包是 JavaScript 生态中最流行的 UUID 库,每周下载量超过 1 亿次。它支持 UUID v1、v3、v4、v5、v7 等所有版本,适合需要特定版本的场景。安装:npm install uuid。对于新项目,如果只需要 UUID v4,优先使用内置的 crypto.randomUUID();如果需要 v5、v7 或其他版本,再使用 uuid 包。
// npm install uuid
import { v1, v4, v5, v7 } from 'uuid';
// UUID v4 (随机)
console.log(v4()); // '110e8400-e29b-41d4-a716-446655440000'
// UUID v1 (时间戳 + MAC)
console.log(v1());
// UUID v5 (命名空间 + 名称,确定性)
const NAMESPACE = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
console.log(v5('https://example.com', NAMESPACE));
// UUID v7 (时间有序,适合数据库主键)
console.log(v7());
在浏览器中不使用外部库生成 UUID
如果需要在不支持 crypto.randomUUID() 的旧浏览器中生成 UUID v4,可以使用 crypto.getRandomValues() 手动实现。这个方法使用加密安全随机数,比 Math.random() 更安全。
// 兼容旧浏览器的 UUID v4 生成
function generateUUID() {
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}
// 或者更清晰的版本
function uuidv4() {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
bytes[6] = (bytes[6] & 0x0f) | 0x40; // 版本 4
bytes[8] = (bytes[8] & 0x3f) | 0x80; // 变体
const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`;
}
在 TypeScript 中使用 UUID
// TypeScript 示例
import { v4 as uuidv4, v7 as uuidv7 } from 'uuid';
interface User {
id: string;
name: string;
createdAt: Date;
}
function createUser(name: string): User {
return {
id: uuidv4(),
name,
createdAt: new Date(),
};
}
// 使用 crypto.randomUUID() - Node.js 18+ 内置类型声明
const id: string = crypto.randomUUID();
// 类型守卫:验证 UUID 格式
function isUUID(str: string): boolean {
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-7][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
return uuidRegex.test(str);
}
React 和 Vue 中的最佳实践
在前端框架中使用 UUID 时,注意以下最佳实践:不要在渲染过程中生成 UUID(否则每次重新渲染都会产生新 ID);在 React 中,用 useState 或 useRef 初始化一次;对于列表渲染的 key,如果数据已有稳定 ID,使用已有 ID 而非临时生成的 UUID;在服务端渲染(SSR)时,客户端和服务端生成的 UUID 不同,可能导致 hydration 不匹配,需要特殊处理。
// React 示例:正确在组件中使用 UUID
import { useState } from 'react';
import { v4 as uuidv4 } from 'uuid';
function TodoItem({ text }) {
// 正确:初始化一次,不会每次渲染都变
const [id] = useState(() => uuidv4());
return {text};
}
// 错误示例(每次渲染都生成新 UUID)
// const id = uuidv4(); // 不要这样写!
性能考虑
JavaScript 中生成 UUID 的性能对大多数场景来说不是瓶颈。crypto.randomUUID() 的性能通常优于 uuid 包(直接调用原生 API),在现代硬件上每秒可生成数百万个 UUID。如果需要批量生成大量 UUID(如数据迁移、初始化种子数据),可以使用循环或 Array.from() 批量生成;如果性能要求极高,可以一次调用 crypto.getRandomValues() 获取多个随机字节,然后从中派生多个 UUID,减少系统调用次数。
立即免费使用相关工具
免费使用 →