تولید UUID v4 در جاوااسکریپت — راهنمای کامل
از تولیدکننده UUID v4 آنلاین رایگان مستقیم در مرورگرتان استفاده کنید — نیازی به نصب نیست.
امتحان کردن تولیدکننده UUID v4 آنلاین ←هر برنامهی جاوااسکریپتی بالاخره به شناسههای یکتا نیاز پیدا میکند — توکنهای سشن، سطرهای پایگاه داده، کلیدهای idempotency برای APIهای پرداخت، شناسههای correlation برای distributed tracing. سادهترین راه برای تولید UUID v4 در جاوااسکریپت امروز crypto.randomUUID() است: بدون وابستگی، یک خط کد، امن از نظر رمزنگاری. UUID v4 دقیقاً به این دلیل فراگیر است که به هماهنگی بین سرویسها نیازی ندارد — کلاینت و سرور میتوانند هر دو به صورت مستقل بدون خطر تصادم ID تولید کنند. این راهنما آن API داخلی، بستهی npm به نام uuid و اعتبارسنجی را پوشش میدهد — همه روی Node.js 19+ و مرورگرهای مدرن. برای گزینهای بدون کد، مولد UUID v4 در ToolDeck شناسههای معتبر را فوری تولید میکند.
- ✓crypto.randomUUID() در مرورگرها و Node.js داخلی است — بدون وابستگی، یک خط کد.
- ✓UUID v4 یک شناسهی ۱۲۸ بیتی تصادفی است: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx (y یکی از ۸، ۹، a یا b است).
- ✓با /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i اعتبارسنجی کنید — نیبلهای نسخه و واریانت را بررسی میکند.
- ✓بستهی uuid در npm پشتیبانی از v1، v3، v5 و v7 را اضافه میکند وقتی به بیش از IDs تصادفی نیاز دارید.
- ✓برای کلیدهای اصلی پایگاه داده، UUID v7 (مرتبشده بر اساس زمان) را به جای v4 (تصادفی) ترجیح دهید تا fragmentation ایندکس کاهش یابد.
UUID v4 چیست؟
UUID (شناسهی یکتای جهانی) نسخه ۴ یک شناسهی ۱۲۸ بیتی تصادفی است که به صورت ۳۲ رقم هگزادسیمال جدا شده با چهار خط تیره فرمت میشود: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx. عدد 4 در موقعیت ۱۵ نسخه را مشخص میکند. کاراکتر y در موقعیت ۲۰ یکی از 8، 9، a یا b است (واریانت RFC 4122). ۱۲۲ بیت باقیمانده تصادفی هستند. UUID v4 رایجترین نسخه در برنامههای جاوااسکریپتی است چون به هماهنگی بین سیستمها نیاز ندارد — میتوانید IDها را به صورت مستقل در کلاینت و سرور بدون نگرانی از تصادم تولید کنید.
// با UUID v4
const event = {
id: "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
action: "user.login",
ts: 1711824000
};// بدون شناسه
const event = { action: "user.login", ts: 1711824000 };crypto.randomUUID() — رویکرد بومی جاوااسکریپت
crypto.randomUUID() در Chrome 92+، Firefox 95+، Safari 15.4+ و Node.js 19+ در دسترس است (با پشتیبانی آزمایشی از Node.js 14.17.0 از طریق globalThis.crypto). یک رشتهی UUID v4 با ۳۶ کاراکتر کوچک برمیگرداند. در جاوااسکریپت مرورگر نیازی به ایمپورت نیست. در Node.js میتوانید مستقیماً روی شیء گلوبال crypto فراخوانی کنید یا آن را به صراحت از ماژول node:crypto ایمپورت کنید.
// در هر مرورگر مدرن کار میکند — بدون مرحله بیلد، بدون bundler
const requestId = crypto.randomUUID();
console.log(requestId);
// "3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f"
// هرجا که به شناسهی یکتا نیاز دارید استفاده کنید
const telemetryEvent = {
event_id: crypto.randomUUID(),
action: "checkout.started",
session_id: crypto.randomUUID(),
timestamp: Date.now(),
cart_total_cents: 14999,
};
console.log(JSON.stringify(telemetryEvent, null, 2));// رویکرد ۱: crypto گلوبال (Node.js 19+)
const orderId = crypto.randomUUID();
console.log(orderId);
// "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
// رویکرد ۲: ایمپورت صریح از node:crypto
import { randomUUID } from 'node:crypto';
const correlationId = randomUUID();
console.log(correlationId);
// "f7e6d5c4-b3a2-4190-8f7e-6d5c4b3a2190"اگر کد شما ممکن است روی مرورگرهای قدیمیتر یا WebViewهای جاسازیشده اجرا شود، بررسی ویژگی crypto.randomUUID ارزش دارد. این بررسی یک گارد سادهی typeof است:
function generateUUIDv4() {
// در صورت وجود، API بومی را ترجیح میدهیم
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
return crypto.randomUUID();
}
// fallback دستی با getRandomValues (بخش بعدی را ببینید)
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
// تنظیم نسخه (4) و واریانت (RFC 4122)
bytes[6] = (bytes[6] & 0x0f) | 0x40; // نسخه 4
bytes[8] = (bytes[8] & 0x3f) | 0x80; // واریانت 10xx
const hex = [...bytes].map(b => b.toString(16).padStart(2, '0'));
return [
hex.slice(0, 4).join(''),
hex.slice(4, 6).join(''),
hex.slice(6, 8).join(''),
hex.slice(8, 10).join(''),
hex.slice(10, 16).join(''),
].join('-');
}
console.log(generateUUIDv4());
// "9b2e4f1a-7c3d-4e8f-a5b6-0d2c1e9f8a7b"crypto.randomUUID() همیشه در دسترس است. در برخی مرورگرها روی صفحات HTTP غیرامن خطا میدهد. اگر برنامهی شما گاهی در مرحلهی توسعه روی HTTP ساده اجرا میشود، fallback getRandomValues بالا آن حالت را پوشش میدهد.تولید UUID v4 بدون کتابخانه
گاهی نمیتوانید به crypto.randomUUID() متکی باشید — شاید یک WebView را هدف قرار دادهاید که API crypto را حذف کرده، یا میخواهید بفهمید زیر هود چه اتفاقی میافتد. رویکرد دستی از crypto.getRandomValues() (از IE 11 در دسترس) برای پر کردن ۱۶ بایت با دادهی تصادفی استفاده میکند، سپس دو عملیات bitmask برای تنظیم فیلدهای نسخه و واریانت اعمال میکند. این دو عملیات تنها تفاوت UUID v4 و یک رشتهی بایت کاملاً تصادفی هستند.
function uuidv4Manual() {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
// تنظیم نسخه: بیتهای ۱۲–۱۵ از بایت ۶ = 0100 (نسخه 4)
bytes[6] = (bytes[6] & 0x0f) | 0x40;
// تنظیم واریانت: بیتهای ۶–۷ از بایت ۸ = 10 (RFC 4122)
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const hex = [...bytes].map(b => b.toString(16).padStart(2, '0'));
return (
hex.slice(0, 4).join('') + '-' +
hex.slice(4, 6).join('') + '-' +
hex.slice(6, 8).join('') + '-' +
hex.slice(8, 10).join('') + '-' +
hex.slice(10, 16).join('')
);
}
const traceId = uuidv4Manual();
console.log(traceId);
// "e4d7c2a1-3f9b-48e5-a612-9d8c7b6a5f4e"
// بررسی اینکه از اعتبارسنجی UUID v4 بگذرد
const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
console.log(UUID_V4_RE.test(traceId)); // trueMath.random() برای تولید UUID استفاده نکنید. از نظر رمزنگاری امن نیست، دورهی خروجی آن خیلی کوتاه است، و برخی موتورها دنبالههای قابل پیشبینی تولید میکنند. همیشه از crypto.getRandomValues() یا crypto.randomUUID() استفاده کنید.بستهی uuid در npm — پشتیبانی از چند نسخه
بستهی uuid در npm از قبل از وجود crypto.randomUUID() کتابخانهی اصلی UUID برای جاوااسکریپت بوده است. در سه موقعیت هنوز منطقی است: وقتی به نسخههای UUID غیر از v4 نیاز دارید (v1، v3، v5، v7)، رانتایمهای قدیمیتر از Node.js 14.17.0 را هدف قرار میدهید، یا تابعهای کمکی validate و parse را میخواهید. برای UUID v4 ساده روی یک رانتایم مدرن، API بومی کافی است و نیازی به وابستگی اضافه نیست.
npm install uuid
import { v4 as uuidv4, validate, version } from 'uuid';
// تولید UUID v4
const paymentId = uuidv4();
console.log(paymentId);
// "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"
// اعتبارسنجی هر رشته UUID
console.log(validate(paymentId)); // true
console.log(validate("not-a-uuid")); // false
// تشخیص نسخه یک UUID
console.log(version(paymentId)); // 4
// تولید دستهای برای seed کردن پایگاه دادهی تست
const testAccounts = Array.from({ length: 5 }, () => ({
account_id: uuidv4(),
plan: "starter",
created_at: new Date().toISOString(),
}));
console.log(testAccounts);uuid داخلاً در مرورگرها از crypto.getRandomValues() و در Node.js از crypto.randomBytes() استفاده میکند، پس منبع آنتروپی یکسان با API بومی است. تفاوت تنها توابع کاربردی اضافه و پشتیبانی از چند نسخه است.اگر ترجیح میدهید اصلاً کد ننویسید، مولد UUID v4 را امتحان کنید — شناسههای v4 سازگار با RFC 4122 را مستقیماً در مرورگر با یک کلیک تولید میکند.
UUIDهای قطعی — تولید UUID v5 از یک رشته
UUID v4 بنا بر تعریف تصادفی است — فراخوانی دوبارهی آن همیشه نتایج متفاوتی میدهد. گاهی به عکس آن نیاز دارید: یک رشتهی ورودی یکسان باید همیشه UUID یکسانی تولید کند. این همان چیزی است که UUID v5 انجام میدهد. یک UUID namespace و یک رشتهی ورودی را با SHA-1 hash میکند، سپس نتیجه را به صورت UUID فرمت میکند. namespace یکسان + ورودی یکسان = خروجی یکسان، همیشه، روی هر دستگاهی. این برای استخراج IDهای پایدار از URLها، آدرسهای ایمیل، یا هر رشتهای که قبلاً یک منبع را شناسایی میکند مفید است.
import { v5 as uuidv5 } from 'uuid';
// namespace داخلی برای URLها (RFC 4122)
const URL_NAMESPACE = uuidv5.URL;
// "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
// یک URL یکسان همیشه UUID یکسان تولید میکند
const pageId1 = uuidv5("https://api.warehouse.dev/products/sku-7291", URL_NAMESPACE);
const pageId2 = uuidv5("https://api.warehouse.dev/products/sku-7291", URL_NAMESPACE);
console.log(pageId1 === pageId2); // true
console.log(pageId1);
// "a6e4e1c0-7e23-5d3b-8f14-9c2a1b3d5e7f"
// namespace سفارشی برای برنامهی شما
const APP_NAMESPACE = "f47ac10b-58cc-4372-a567-0e02b2c3d479";
const tenantId = uuidv5("acme-corp", APP_NAMESPACE);
console.log(tenantId);
// "d4735e3a-265b-564e-8f32-7a1b2c3d4e5f"یک نکتهی سریع: UUID v3 همین کار را میکند اما با MD5 به جای SHA-1. برای پروژههای جدید v5 را ترجیح دهید. MD5 آسیبپذیریهای تصادم شناختهشده دارد، و اگرچه برای تولید ID خیلی مهم نیست، وقتی هر دو در دسترس هستند دلیلی برای انتخاب آن به جای SHA-1 وجود ندارد.
مرجع crypto.randomUUID() و APIهای مرتبط
API بومی crypto.randomUUID() هیچ آرگومانی نمیگیرد — یک رشته برمیگرداند و تمام. از آن استفاده کنید وقتی به شناسههای سازگار با RFC 4122 بدون هیچ وابستگی نیاز دارید. وقتی به جای رشتهی UUID فرمتشده به بایتهای تصادفی خام نیاز دارید — مثلاً برای پر کردن یک typed array یا استخراج کلید — مستقیماً از crypto.getRandomValues() استفاده کنید. APIهای مرتبطی که برای کار با UUID اهمیت دارند در زیر فهرست شدهاند.
تفکیک الگوی regex مربوط به UUID v4:
اعتبارسنجی UUID v4 با Regex
اعتبارسنجی اینکه یک رشته UUID v4 معتبر است مدام پیش میآید — بدنهی درخواستهای ورودی API، پارامترهای URL، بارهای webhook. یک regex دستنوشته انتخاب درستی است وقتی هیچ وابستگی نمیخواهید و فقط v4 را اعتبارسنجی میکنید. اگر قبلاً از بستهی uuid استفاده میکنید، به جای آن export validate() آن را ترجیح دهید — تمام نسخههای UUID را پوشش میدهد و کمتر از نگهداری یک الگوی سفارشی خطاپذیر است. regex /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i هم نیبل نسخه (باید 4 باشد) و هم نیبل واریانت (باید 8، 9، a یا b باشد) را بررسی میکند. از RegExp.prototype.test() برای بررسیهای boolean و .match() وقتی میخواهید UUID را از متن اطراف استخراج کنید استفاده کنید.
const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
function isUUIDv4(str) {
return UUID_V4_RE.test(str);
}
// UUID v4 معتبر
console.log(isUUIDv4("9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d")); // true
// UUID v1 — نیبل نسخه ۱ است نه ۴
console.log(isUUIDv4("550e8400-e29b-11d4-a716-446655440000")); // false
// UUID v7 — نیبل نسخه ۷ است
console.log(isUUIDv4("018e4a0c-5b3f-7d12-8a9b-0c1d2e3f4a5b")); // false
// رشتههای ناقص
console.log(isUUIDv4("not-a-uuid")); // false
console.log(isUUIDv4("")); // false
console.log(isUUIDv4("9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d")); // false (بدون خط تیره)
// استخراج UUID از یک رشته بزرگتر
const logLine = 'Request req_id=9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d failed with 503';
const match = logLine.match(/[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i);
console.log(match?.[0]);
// "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"تولید و اتصال UUIDها از فایل و پاسخ API
در عمل، به ندرت crypto.randomUUID() را به تنهایی فراخوانی میکنید. دو الگو مدام پیش میآید: اختصاص ID به رکوردها قبل از نوشتن آنها در پایگاه داده، و اتصال شناسههای correlation به درخواستهای API خروجی تا بتوانید یک درخواست را در سرویسهای مختلف در لاگهایتان ردیابی کنید.
خواندن فایل NDJSON → اختصاص UUIDها → نوشتن مجدد
import { readFileSync, writeFileSync } from 'node:fs';
import { randomUUID } from 'node:crypto';
function assignIds(inputPath, outputPath) {
const lines = readFileSync(inputPath, 'utf-8')
.split('\n')
.filter(line => line.trim());
const records = lines.map(line => {
try {
const record = JSON.parse(line);
if (!record.id) {
record.id = randomUUID();
}
return JSON.stringify(record);
} catch (err) {
console.error(`Skipping malformed line: ${err.message}`);
return null;
}
}).filter(Boolean);
writeFileSync(outputPath, records.join('\n') + '\n');
console.log(`Assigned IDs to ${records.length} records → ${outputPath}`);
}
assignIds('warehouse-products.ndjson', 'warehouse-products-with-ids.ndjson');
// Assigned IDs to 1284 records → warehouse-products-with-ids.ndjsonاتصال شناسه Correlation به درخواست API خروجی
import { randomUUID } from 'node:crypto';
async function createShipment(orderPayload) {
const correlationId = randomUUID();
try {
const response = await fetch('https://api.logistics.dev/v2/shipments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Correlation-ID': correlationId,
'X-Idempotency-Key': randomUUID(),
},
body: JSON.stringify(orderPayload),
});
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`Shipment API returned ${response.status}: ${errorBody}`);
}
const result = await response.json();
console.log(`Shipment created: ${result.shipment_id} (correlation: ${correlationId})`);
return result;
} catch (err) {
console.error(`[correlation:${correlationId}] Shipment failed: ${err.message}`);
throw err;
}
}
await createShipment({
order_id: "ord_8a3f91bc",
destination: { city: "تهران", state: "تهران", zip: "1234567891" },
items: [{ sku: "WH-7291", quantity: 2, weight_kg: 1.4 }],
});تولید UUID از خط فرمان
همیشه به اسکریپت نیاز ندارید. Node.js میتواند مستقیماً از خط فرمان UUID تولید کند، که برای اسکریپتهای shell، خطوط CI و تستهای یکبار مصرف مفید است. فلگ -e یک عبارت تنها را ارزیابی میکند.
# یک UUID node -e "console.log(crypto.randomUUID())" # 3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f # پنج UUID همزمان node -e "for(let i=0;i<5;i++) console.log(crypto.randomUUID())" # تولید و اختصاص به یک متغیر shell export REQUEST_ID=$(node -e "process.stdout.write(crypto.randomUUID())") echo "Request ID: $REQUEST_ID" # استفاده از npx uuid (اگر بسته را به صورت گلوبال نصب دارید یا میخواهید یک بار اجرا کنید) npx uuid v4 # 1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed
# DevTools هر مرورگری را باز کنید و تایپ کنید: crypto.randomUUID() # "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
uuidgen روی macOS و اکثر توزیعهای لینوکس از پیش نصب است. روی سیستمهای مدرن به صورت پیشفرض UUID v4 تولید میکند.جایگزین پرسرعت — nanoid
اگر هزاران ID در ثانیه تولید میکنید و فرمت ۳۶ کاراکتری UUID الزامی نیست، به nanoid فکر کنید. ۲ برابر از uuid.v4() سریعتر است، به صورت پیشفرض یک ID URL-safe با ۲۱ کاراکتر تولید میکند و پس از minification حدود ۱ کیلوبایت وزن دارد. خروجی UUID نیست — یک ID با الفبای سفارشی است — پس در جایی که سازگاری با RFC 4122 لازم است استفاده نکنید (ستونهای UUID پایگاه داده، APIهایی که فرمت UUID اعتبارسنجی میکنند، trace IDهای OpenTelemetry). اما برای شناسههای correlation داخلی، کلیدهای React component و slugهای URL، مناسب است.
npm install nanoid
import { nanoid, customAlphabet } from 'nanoid';
// پیشفرض: ID URL-safe با ۲۱ کاراکتر (A-Za-z0-9_-)
const trackingCode = nanoid();
console.log(trackingCode);
// "V1StGXR8_Z5jdHi6B-myT"
// طول سفارشی
const shortCode = nanoid(10);
console.log(shortCode);
// "IRFa-VaY2b"
// الفبای سفارشی — فقط اعداد، ۱۲ رقم
const numericId = customAlphabet('0123456789', 12);
console.log(numericId());
// "839274651023"
// الفبای سفارشی — فقط هگز، ۳۲ کاراکتر (همان آنتروپی UUID v4 بدون خط تیره)
const hexId = customAlphabet('0123456789abcdef', 32);
console.log(hexId());
// "4f8a1b2c3d7e9f0a5b6c8d1e2f3a4b5c"خروجی ترمینال با Syntax Highlighting
اشکالزدایی برنامههای UUID-heavy به معنای خیره شدن به دیوارهایی از رشتههای هگز در ترمینال است. رنگبندی کمک میکند. کتابخانهی chalk (یا node:util جدیدتر با styleText در Node.js 21.7+) به شما امکان میدهد UUIDها را در خروجی لاگ برجسته کنید تا از متن اطراف متمایز شوند.
import chalk from 'chalk';
import { randomUUID } from 'node:crypto';
function logEvent(action, metadata = {}) {
const eventId = randomUUID();
const timestamp = new Date().toISOString();
console.log(
chalk.gray(timestamp),
chalk.cyan(eventId),
chalk.white(action),
Object.keys(metadata).length
? chalk.dim(JSON.stringify(metadata))
: ''
);
}
logEvent('shipment.created', { order_id: 'ord_8a3f', carrier: 'fedex' });
logEvent('payment.captured', { amount_cents: 14999, currency: 'USD' });
logEvent('webhook.delivered', { endpoint: 'https://hooks.acme.dev/orders' });
// 2026-03-27T10:15:00.000Z a1b2c3d4-... shipment.created {"order_id":"ord_8a3f",...}تولید IDهای یکتای کوتاه در جاوااسکریپت
یک UUID با ۳۶ کاراکتر گاهی خیلی طولانی است — slugهای URL، دادههای QR code، پیامهای SMS و پروتکلهای سختافزار جاسازیشده همه محدودیت طول دارند.
import { randomUUID } from 'node:crypto';
// ۱. حذف خط تیره از UUID v4 → رشته هگز ۳۲ کاراکتری
const hex32 = randomUUID().replaceAll('-', '');
console.log(hex32);
// "3e7f1a924b0c4d8e9f127a6b3c8d5e1f" (۳۲ کاراکتر)
// ۲. Base64 کردن ۱۶ بایت تصادفی → رشته ۲۲ کاراکتری (URL-safe)
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
const base64Id = Buffer.from(bytes)
.toString('base64url')
.replace(/=+$/, '');
console.log(base64Id);
// "Pj8akksNTY6fEnarPIvR" (۲۲ کاراکتر، ۱۲۸ بیت آنتروپی)
// ۳. nanoid با طول سفارشی
import { nanoid } from 'nanoid';
const short12 = nanoid(12);
console.log(short12);
// "V1StGXR8_Z5j" (۱۲ کاراکتر، ~۷۱ بیت آنتروپی)محاسبهی احتمال تصادم: یک nanoid با ۱۲ کاراکتر (الفبای پیشفرض ۶۴ کاراکتری) تقریباً ۷۱ بیت آنتروپی میدهد. با ۱۰۰۰ ID در ثانیه، برای رسیدن به ۱٪ احتمال تصادم حدود ۱۱۶ سال نیاز است. برای اکثر برنامهها این بیش از کافی است. اگر میلیونها ID در روز تولید میکنید، از UUID کامل یا nanoid با حداقل ۲۱ کاراکتر استفاده کنید.
UUID v7 — جایگزین مرتبشده بر اساس زمان v4
UUID v7 (تعریفشده در RFC 9562) یک timestamp یونیکس ۴۸ بیتی با دقت میلیثانیه در بخش اول، سپس بیتهای تصادفی جاسازی میکند. نتیجه یک UUID است که شبیه v4 به نظر میرسد اما به صورت زمانی مرتب میشود. این آن را برای کلیدهای اصلی پایگاه داده بهتر از v4 میکند: سطرهای جدید همیشه در انتهای ایندکس B-tree قرار میگیرند نه در موقعیتهای تصادفی، که page split و fragmentation را کاهش میدهد. در پروژههایی که برای جدول Postgres به IDهای مرتبشده بر اساس زمان نیاز دارم، فوری به v7 میروم — تفاوت عملکرد ایندکس در مقیاس قابل اندازهگیری است. مولد UUID v7 در ToolDeck timestamp تعبیهشده را برای هر UUID v7 نشان میدهد.
import { v7 as uuidv7 } from 'uuid';
// تولید سه مقدار UUID v7 — توجه کنید که به صورت زمانی مرتب میشوند
const id1 = uuidv7();
const id2 = uuidv7();
const id3 = uuidv7();
console.log(id1);
// "018e4a0c-5b3f-7d12-8a9b-0c1d2e3f4a5b"
console.log(id2);
// "018e4a0c-5b40-7e34-9c2d-1e4f5a6b7c8d"
console.log(id3);
// "018e4a0c-5b41-7f56-ae3f-2a5b6c7d8e9f"
// به صورت لغوی بر اساس زمان ایجاد مرتب میشوند
console.log([id3, id1, id2].sort());
// [id1, id2, id3] — ترتیب زمانی حفظ میشود
// از v4 برای توکنهایی استفاده کنید که زمانبندی نباید فاش شود
import { v4 as uuidv4 } from 'uuid';
const sessionToken = uuidv4(); // کاملاً تصادفی، بدون اطلاعات زمانیuuid از نسخه ۹.۰.۰ به بعد از v7 پشتیبانی میکند. اگر نسخهی قدیمیتری دارید، npm install uuid@latest را برای ارتقاء اجرا کنید.UUID v4 در مرورگر بدون مرحلهی Build
بدون bundler، بدون npm، بدون transpiler. فقط یک فایل HTML ساده. این سادهترین روش ممکن برای تولید UUID در جاوااسکریپت سمت کلاینت است. کار میکند چون crypto.randomUUID() یک API داخلی مرورگر است.
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>UUID Generator</title></head>
<body>
<p>Your UUID: <strong id="output"></strong></p>
<button onclick="document.getElementById('output').textContent = crypto.randomUUID()">
Generate
</button>
<script>
// یکی را هنگام بارگذاری صفحه تولید میکند
document.getElementById('output').textContent = crypto.randomUUID();
</script>
</body>
</html>همین فایل کامل است. بدون ایمپورت CDN، بدون تگهای script که کتابخانهها را بارگذاری کنند. برای هر چیز پیچیدهتر — تولید دستهای، اعتبارسنجی، IDهای قطعی — بستهی uuid یا fallback دستی نشاندادهشده را میخواهید. اما برای یک prototype سریع یا ابزار داخلی، همین کافی است.
اشتباهات رایج
الگوی UUID مبتنی بر Math.random() را بیشتر از آنچه دوست داشتم از پستهای بلاگ قدیمی در کد production کپیشده دیدهام. باگهایی که این الگوها ایجاد میکنند ساکت هستند: بدون خطای runtime، فقط رفتار ظریفاً اشتباه که دیرتر زیر بار یا در بررسیهای امنیتی آشکار میشود.
مشکل: Math.random() از نظر رمزنگاری امن نیست. خروجی آن در برخی موتورها قابل پیشبینی است، و آنتروپی پایین احتمال تصادم را بسیار بیشتر از یک CSPRNG مناسب میکند.
راهحل: همیشه از crypto.randomUUID() یا crypto.getRandomValues() استفاده کنید. هر دو از CSPRNG سیستمعامل استفاده میکنند.
// امن — از CSPRNG سیستمعامل استفاده میکند
const id = crypto.randomUUID();
// یا اگر به fallback دستی نیاز دارید:
function secureUuid() {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const h = [...bytes].map(b => b.toString(16).padStart(2, '0'));
return `${h.slice(0,4).join('')}-${h.slice(4,6).join('')}-${h.slice(6,8).join('')}-${h.slice(8,10).join('')}-${h.slice(10).join('')}`;
}// ناامن — قابل پیشبینی، آنتروپی پایین
function badUuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
/[xy]/g,
c => {
const r = Math.random() * 16 | 0;
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
}
);
}مشکل: crypto.randomUUID() هگز کوچک برمیگرداند، اما UUIDهای سیستمهای دیگر (پایگاههای داده، APIها، ورودی کاربر) ممکن است از حروف بزرگ استفاده کنند. مقایسهی مستقیم === وقتی حالتها متفاوت باشند شکست میخورد.
راهحل: هر دو طرف را قبل از مقایسه به حروف کوچک نرمال کنید.
const fromApi = "9B1DEB4D-3B7D-4BAD-9BDD-2B0D7B3DCB6D";
const local = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d";
if (fromApi.toLowerCase() === local.toLowerCase()) {
// به درستی تطبیق مییابد
}const fromApi = "9B1DEB4D-3B7D-4BAD-9BDD-2B0D7B3DCB6D"; // حروف بزرگ از API
const local = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"; // حروف کوچک از crypto
if (fromApi === local) { /* هرگز اجرا نمیشود */ }مشکل: برخی کتابخانههای UUID (مخصوصاً در زبانهای دیگر) شیء UUID برمیگردانند. در جاوااسکریپت، قرار دادن تصادفی یک رشته UUID در یک شیء بررسی برابری، JSON serialization و queryهای پایگاه داده را خراب میکند.
راهحل: UUIDها را همیشه به صورت رشتهی ساده ذخیره و منتقل کنید. اگر کتابخانهای شیء برمیگرداند، فوری .toString() را فراخوانی کنید یا به خاصیت رشته دسترسی داشته باشید.
// فقط از رشته استفاده کنید
const id = crypto.randomUUID();
console.log(JSON.stringify({ id }));
// {"id":"3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f"}// ایجاد wrapper غیرضروری
class UUID {
constructor(value) { this.value = value; }
}
const id = new UUID(crypto.randomUUID());
console.log(id === id); // true، اما...
console.log(JSON.stringify({ id })); // {"id":{"value":"..."}}مشکل: UUID v4 کاملاً تصادفی است. مرتبسازی بر اساس UUID v4 ترتیب دلبخواه میدهد نه ترتیب ایجاد. این منجر به صفحهبندی غیرقابل پیشبینی، رابطهای admin گیجکننده و عملکرد بد ایندکس پایگاه داده میشود.
راهحل: از UUID v7 استفاده کنید وقتی به شناسههای مرتبشده بر اساس زمان نیاز دارید. UUID v4 را برای توکنها و شناسههای correlation که ترتیب مرتبسازی بیاهمیت است نگه دارید.
import { v7 as uuidv7 } from 'uuid';
// خوب: v7 بر اساس زمان ایجاد مرتب میشود
const rows = [
{ id: uuidv7(), created: "2026-03-27" },
{ id: uuidv7(), created: "2026-03-26" },
];
rows.sort((a, b) => a.id.localeCompare(b.id));
// ترتیب مرتبسازی با زمان ایجاد مطابقت دارد// بد: استفاده از v4 به عنوان کلید اصلی قابل مرتبسازی
const rows = [
{ id: crypto.randomUUID(), created: "2026-03-27" },
{ id: crypto.randomUUID(), created: "2026-03-26" },
];
rows.sort((a, b) => a.id.localeCompare(b.id));
// ترتیب مرتبسازی تصادفی است — نه بر اساس تاریخ ایجادمقایسهی سریع crypto.randomUUID() در مقابل uuid در مقابل nanoid
برای اکثر پروژههای جاوااسکریپت: از crypto.randomUUID() استفاده کنید وقتی فقط به UUID v4 نیاز دارید و رانتایم شما بهاندازه کافی جدید است. به بستهی uuid دست بزنید وقتی به پشتیبانی v5 (قطعی) یا v7 (مرتبشده بر اساس زمان) نیاز دارید. از nanoid استفاده کنید وقتی یک ID کوتاه URL-safe از UUID با ۳۶ کاراکتر عملیتر است — اما به یاد داشته باشید خروجی nanoid با UUID سازگار نیست و در هر سیستمی که فرمت RFC 4122 را اعتبارسنجی میکند شکست میخورد.
برای گزینهای بدون کد، مولد UUID v4 را امتحان کنید تا شناسهها را فوری در مرورگر بسازید. برای بررسی یک UUID موجود، آن را در رمزگشای UUID paste کنید تا نسخه، واریانت و هر دادهی timestamp تعبیهشده را ببینید.
سوالات متداول
چگونه در جاوااسکریپت یک UUID v4 تولید کنم؟
در هر مرورگر مدرن (Chrome 92+، Firefox 95+، Safari 15.4+) یا Node.js 19+ کافی است crypto.randomUUID() را فراخوانی کنید. این تابع یک رشتهی کوچک مانند "3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f" برمیگرداند. در مرورگرها نیازی به ایمپورت ندارید چون crypto یک گلوبال داخلی است؛ در Node.js میتوانید با import { randomUUID } from "node:crypto" هم آن را به صراحت وارد کنید. برای نسخههای قدیمیتر از Node.js 19 هنوز میتوان crypto.randomUUID() را روی گلوبال فراخوانی کرد — از Node.js 14.17.0 به صورت آزمایشی در دسترس بود. اگر گزینهای بدون کد میخواهید، مولد UUID v4 در /en/uuid/v4 در یک کلیک شناسههای معتبر تولید میکند.
const sessionId = crypto.randomUUID(); console.log(sessionId); // "3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f"
آیا crypto.randomUUID() از نظر رمزنگاری امن است؟
بله. crypto.randomUUID() از همان CSPRNG (مولد اعداد شبهتصادفی امن از نظر رمزنگاری) استفاده میکند که پشتوانهی crypto.getRandomValues() است. ۱۲۲ بیت تصادفی در یک UUID v4 احتمال تصادم را برای همهی کاربردهای عملی ناچیز میکند. برای رسیدن به ۵۰٪ احتمال یک تصادم، تنها باید حدود ۲.۷۱ کوینتیلیون UUID تولید کرد. آنتروپی از منبع تصادفی سیستمعامل میآید (/dev/urandom در لینوکس، BCryptGenRandom در ویندوز) و نه از Math.random() که بهصراحت امن نیست. در نتیجه، مقادیر UUID v4 برای توکنهای سشن، توکنهای CSRF و دیگر شناسههای حساس امنیتی مناسباند. هرگز مولدهای UUID مبتنی بر Math.random() را در زمینههای امنیتی بهکار نبرید.
آیا میتوانم UUID v4 را به عنوان کلید اصلی پایگاه داده استفاده کنم؟
میتوانید، اما یک مصالحهی عملکردی مهم وجود دارد. UUID v4 کاملاً تصادفی است. به همین دلیل ایندکسهای B-tree به شدت دچار fragmentation میشوند، چون هر سطر جدید در یک موقعیت تصادفی در ایندکس درج میشود نه در انتها. در جداول با نوشتن زیاد، این باعث page split و cache miss بیش از حد میشود و عملکرد INSERT و range-scan را کاهش میدهد. اگر پایگاه دادهی شما از آن پشتیبانی میکند (PostgreSQL، MySQL 8.0+، SQL Server)، UUID v7 (مرتبشده بر اساس زمان) کلید اصلی بهتری است. UUID v4 برای توکنهای سشن، پارامترهای OAuth state، کلیدهای idempotency، شناسههای correlation و هر فیلدی که پنهان کردن زمان ایجاد مطلوب باشد، انتخاب درستی است.
// UUID v4 — تصادفی، قابل مرتبسازی نیست
const correlationId = crypto.randomUUID();
// UUID v7 — مرتبشده بر اساس زمان، برای کلید اصلی DB بهتر است
import { v7 as uuidv7 } from 'uuid';
const rowId = uuidv7();تفاوت UUID v4 و UUID v7 چیست؟
UUID v4 با ۱۲۲ بیت دادهی تصادفی پر میشود — هر بخش عملاً نویز است. UUID v7 (RFC 9562، منتشرشده در ۲۰۲۴) یک timestamp یونیکس ۴۸ بیتی با دقت میلیثانیه در بخش اول، ۱۲ بیت دقت زیر میلیثانیه در بخش دوم، و بیتهای تصادفی در بقیه کدگذاری میکند. هر دو ۱۲۸ بیت هستند و از همان فرمت ۳۶ کاراکتری با خط تیره استفاده میکنند، پس در لایهی ذخیرهسازی جایگزینپذیرند. UUID v7 بهصورت لغوی بر اساس زمان ایجاد مرتب میشود که ایندکسهای B-tree را فشرده نگه میدارد و range query روی پنجرههای زمانی را کارآمد میکند. UUID v4 را انتخاب کنید وقتی ID نباید زمان ایجاد را فاش کند — مثلاً توکنهای عمومی که اطلاعات زمانی میتواند مورد سوءاستفاده قرار گیرد — و UUID v7 را برای کلیدهای اصلی پایگاه داده، لاگهای audit و جریانهای رویداد که ترتیب زمانی مهم است.
چگونه یک رشته UUID v4 را در جاوااسکریپت اعتبارسنجی کنم؟
در برابر regex /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i تست کنید. عدد ثابت "4" در موقعیت ۱۵ (zero-indexed) نیبل نسخه را تأیید میکند؛ کاراکتر موقعیت ۲۰ — یکی از ۸، ۹، a یا b — بیتهای واریانت RFC 4122 را کدگذاری میکند. این regex به درستی UUID v1، v7 و هر رشتهی ناقصی را رد میکند. فلگ i آن را case-insensitive میکند تا رقمهای هگز بزرگ از سیستمهای دیگر بدون نرمالسازی از اعتبارسنجی بگذرند. اگر فقط میخواهید بدانید آیا یک رشته هر UUID معتبری است (صرف نظر از نسخه)، به جای آن از الگوی شلتر /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i استفاده کنید.
const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
UUID_V4_RE.test("550e8400-e29b-41d4-a716-446655440000"); // true
UUID_V4_RE.test("550e8400-e29b-11d4-a716-446655440000"); // false (v1)
UUID_V4_RE.test("not-a-uuid"); // falseچگونه یک شناسه کوتاه یکتا در جاوااسکریپت تولید کنم؟
خط تیرههای UUID v4 را حذف کنید تا یک رشتهی هگز ۳۲ کاراکتری بگیرید: crypto.randomUUID().replaceAll("-", ""). برای چیزی حتی کوتاهتر، از nanoid استفاده کنید که به صورت پیشفرض یک ID URL-safe با ۲۱ کاراکتر (A–Z، a–z، ۰–۹، _ و -) با مقاومت در برابر تصادم قابل مقایسه با UUID کامل تولید میکند. مصالحه ساده است: IDs کوتاهتر احتمال تصادم بیشتری دارند، اما nanoid با ۲۱ کاراکتر هنوز ۱۲۶ بیت آنتروپی فراهم میکند که برای تقریباً هر کاربرد واقعی کافی است. برای slugهای URL و دادههای QR code میتوانید به ۱۰–۱۲ کاراکتر با nanoid بروید قبل از اینکه احتمال تصادم در نرخهای تولید معمولی نگرانکننده شود. از Base64 کردن یک UUID خام و قطع کردن آن اجتناب کنید — قطع کردن استقلال آماری بیتها را از بین میبرد و استدلال درباره تصادم را سختتر میکند.
// رشته هگز ۳۲ کاراکتری از UUID v4
const hexId = crypto.randomUUID().replaceAll('-', '');
// "3e7f1a924b0c4d8e9f127a6b3c8d5e1f"
// ID URL-safe با ۲۱ کاراکتر از طریق nanoid
import { nanoid } from 'nanoid';
const shortId = nanoid();
// "V1StGXR8_Z5jdHi6B-myT"ابزارهای مرتبط
Sophie is a full-stack developer focused on TypeScript across the entire stack — from React frontends to Express and Fastify backends. She has a particular interest in type-safe API design, runtime validation, and the patterns that make large JavaScript codebases stay manageable. She writes about TypeScript idioms, Node.js internals, and the ever-evolving JavaScript module ecosystem.
Marcus specialises in JavaScript performance, build tooling, and the inner workings of the V8 engine. He has spent years profiling and optimising React applications, working on bundler configurations, and squeezing every millisecond out of critical rendering paths. He writes about Core Web Vitals, JavaScript memory management, and the tools developers reach for when performance really matters.