ToolDeck

تولید UUID v4 در جاوااسکریپت — راهنمای کامل

·TypeScript & Full-stack Developer·بررسی‌شده توسطMarcus Webb·منتشر شده

از تولیدکننده 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‌ها را به صورت مستقل در کلاینت و سرور بدون نگرانی از تصادم تولید کنید.

After · javascript
Before · javascript
// با 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));
Node.js — دو رویکرد معادل
// رویکرد ۱: 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 است:

جاوااسکریپت — تشخیص ویژگی با fallback
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"
نکته:در زمینه‌های امن (صفحات HTTPS، localhost، افزونه‌های مرورگر)، crypto.randomUUID() همیشه در دسترس است. در برخی مرورگرها روی صفحات HTTP غیرامن خطا می‌دهد. اگر برنامه‌ی شما گاهی در مرحله‌ی توسعه روی HTTP ساده اجرا می‌شود، fallback getRandomValues بالا آن حالت را پوشش می‌دهد.

تولید UUID v4 بدون کتابخانه

گاهی نمی‌توانید به crypto.randomUUID() متکی باشید — شاید یک WebView را هدف قرار داده‌اید که API crypto را حذف کرده، یا می‌خواهید بفهمید زیر هود چه اتفاقی می‌افتد. رویکرد دستی از crypto.getRandomValues() (از IE 11 در دسترس) برای پر کردن ۱۶ بایت با داده‌ی تصادفی استفاده می‌کند، سپس دو عملیات bitmask برای تنظیم فیلدهای نسخه و واریانت اعمال می‌کند. این دو عملیات تنها تفاوت UUID v4 و یک رشته‌ی بایت کاملاً تصادفی هستند.

جاوااسکریپت — UUID v4 دستی با getRandomValues
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)); // true
هشدار:هرگز از Math.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 بومی کافی است و نیازی به وابستگی اضافه نیست.

bash — نصب
npm install uuid
جاوااسکریپت — بسته uuid برای تولید v4
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ها، آدرس‌های ایمیل، یا هر رشته‌ای که قبلاً یک منبع را شناسایی می‌کند مفید است.

جاوااسکریپت — uuid v5 برای IDهای قطعی
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 اهمیت دارند در زیر فهرست شده‌اند.

ویژگی / متد
نوع بازگشتی
توضیحات
crypto.randomUUID()
string
یک رشته UUID v4 با ۳۶ کاراکتر به صورت حروف کوچک هگزادسیمال با خط تیره برمی‌گرداند
crypto.getRandomValues(arr)
TypedArray
یک آرایه‌ی typed را با مقادیر تصادفی رمزنگاری‌شده پر می‌کند — پایه‌ی تولید دستی UUID
URL.createObjectURL(blob)
string
یک URL بلاب یکتا تولید می‌کند (UUID نیست، اما گاهی با آن اشتباه گرفته می‌شود)

تفکیک الگوی regex مربوط به UUID v4:

بخش
الگو
معنا
[0-9a-f]{8}
xxxxxxxx
۸ رقم هگز اول — ۳۲ بیت تصادفی
[0-9a-f]{4}
xxxx
۴ رقم هگز بعدی — ۱۶ بیت تصادفی
4[0-9a-f]{3}
4xxx
نیبل نسخه ثابت روی ۴، سپس ۱۲ بیت تصادفی
[89ab][0-9a-f]{3}
yxxx
نیبل واریانت یکی از ۸، ۹، a یا b است — سپس ۱۲ بیت تصادفی
[0-9a-f]{12}
xxxxxxxxxxxx
۱۲ رقم هگز پایانی — ۴۸ بیت تصادفی

اعتبارسنجی 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 را از متن اطراف استخراج کنید استفاده کنید.

جاوااسکریپت — تابع کمکی اعتبارسنجی 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;

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ها → نوشتن مجدد

Node.js — اختصاص 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 خروجی

Node.js — شناسه correlation برای distributed tracing
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 یک عبارت تنها را ارزیابی می‌کند.

bash — تولید UUID از خط فرمان
# یک 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
bash — تولید UUID در کنسول مرورگر (بدون Node.js)
# DevTools هر مرورگری را باز کنید و تایپ کنید:
crypto.randomUUID()
# "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
نکته:اگر در CI pipeline به UUID نیاز دارید و Node.js در دسترس نیست، 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، مناسب است.

bash — نصب nanoid
npm install nanoid
جاوااسکریپت — nanoid برای IDهای یکتای کوتاه
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ها را در خروجی لاگ برجسته کنید تا از متن اطراف متمایز شوند.

Node.js — خروجی UUID رنگی با chalk
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",...}
هشدار:کدهای escape رنگ فایل‌های لاگ را خراب می‌کنند و JSON parserها را می‌شکنند. از chalk یا styleText فقط برای خروجی ترمینالی که انسان مستقیماً می‌خواند استفاده کنید. برای لاگ‌های ساختاریافته‌ای که به فایل یا aggregator لاگ می‌روند، از JSON ساده استفاده کنید.

تولید IDهای یکتای کوتاه در جاوااسکریپت

یک UUID با ۳۶ کاراکتر گاهی خیلی طولانی است — slug‌های URL، داده‌های QR code، پیام‌های SMS و پروتکل‌های سخت‌افزار جاسازی‌شده همه محدودیت طول دارند.

جاوااسکریپت — سه تکنیک برای IDهای کوتاه‌تر
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 نشان می‌دهد.

جاوااسکریپت — UUID v7 با بسته uuid
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 داخلی مرورگر است.

HTML — مولد UUID مینیمال در مرورگر
<!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() برای تولید UUID

مشکل: Math.random() از نظر رمزنگاری امن نیست. خروجی آن در برخی موتورها قابل پیش‌بینی است، و آنتروپی پایین احتمال تصادم را بسیار بیشتر از یک CSPRNG مناسب می‌کند.

راه‌حل: همیشه از crypto.randomUUID() یا crypto.getRandomValues() استفاده کنید. هر دو از CSPRNG سیستم‌عامل استفاده می‌کنند.

After · JavaScript
Before · JavaScript
// امن — از 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);
    }
  );
}
مقایسه‌ی UUIDها با برابری case-sensitive

مشکل: crypto.randomUUID() هگز کوچک برمی‌گرداند، اما UUIDهای سیستم‌های دیگر (پایگاه‌های داده، APIها، ورودی کاربر) ممکن است از حروف بزرگ استفاده کنند. مقایسه‌ی مستقیم === وقتی حالت‌ها متفاوت باشند شکست می‌خورد.

راه‌حل: هر دو طرف را قبل از مقایسه به حروف کوچک نرمال کنید.

After · JavaScript
Before · JavaScript
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 برمی‌گردانند. در جاوااسکریپت، قرار دادن تصادفی یک رشته UUID در یک شیء بررسی برابری، JSON serialization و query‌های پایگاه داده را خراب می‌کند.

راه‌حل: UUID‌ها را همیشه به صورت رشته‌ی ساده ذخیره و منتقل کنید. اگر کتابخانه‌ای شیء برمی‌گرداند، فوری .toString() را فراخوانی کنید یا به خاصیت رشته دسترسی داشته باشید.

After · JavaScript
Before · JavaScript
// فقط از رشته استفاده کنید
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 کاملاً تصادفی است. مرتب‌سازی بر اساس UUID v4 ترتیب دلبخواه می‌دهد نه ترتیب ایجاد. این منجر به صفحه‌بندی غیرقابل پیش‌بینی، رابط‌های admin گیج‌کننده و عملکرد بد ایندکس پایگاه داده می‌شود.

راه‌حل: از UUID v7 استفاده کنید وقتی به شناسه‌های مرتب‌شده بر اساس زمان نیاز دارید. UUID v4 را برای توکن‌ها و شناسه‌های correlation که ترتیب مرتب‌سازی بی‌اهمیت است نگه دارید.

After · JavaScript
Before · JavaScript
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

روش
فرمت خروجی
نسخه‌های UUID
حجم Bundle
انواع سفارشی
نیاز به نصب
crypto.randomUUID()
UUID v4 با ۳۶ کاراکتر
فقط v4
۰ کیلوبایت
ندارد
خیر (داخلی)
بسته uuid در npm
UUID با ۳۶ کاراکتر
v1, v3, v4, v5, v6, v7
~۶.۵ کیلوبایت
ندارد
npm install
nanoid
شناسه URL-safe با ۲۱ کاراکتر
سفارشی (UUID نیست)
~۱ کیلوبایت
ندارد
npm install
getRandomValues دستی
UUID v4 با ۳۶ کاراکتر
فقط v4
۰ کیلوبایت
ندارد
خیر (داخلی)
crypto.randomBytes (Node)
Buffer → UUID v4 با ۳۶ کاراکتر
فقط v4
۰ کیلوبایت
ندارد
خیر (داخلی Node)
بسته uuidv7 در npm
UUID v7 با ۳۶ کاراکتر
فقط v7
~۲ کیلوبایت
ندارد
npm install

برای اکثر پروژه‌های جاوااسکریپت: از 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 در یک کلیک شناسه‌های معتبر تولید می‌کند.

JavaScript
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 و هر فیلدی که پنهان کردن زمان ایجاد مطلوب باشد، انتخاب درستی است.

JavaScript
// 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 استفاده کنید.

JavaScript
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 خام و قطع کردن آن اجتناب کنید — قطع کردن استقلال آماری بیت‌ها را از بین می‌برد و استدلال درباره تصادم را سخت‌تر می‌کند.

JavaScript
// رشته هگز ۳۲ کاراکتری از UUID v4
const hexId = crypto.randomUUID().replaceAll('-', '');
// "3e7f1a924b0c4d8e9f127a6b3c8d5e1f"

// ID URL-safe با ۲۱ کاراکتر از طریق nanoid
import { nanoid } from 'nanoid';
const shortId = nanoid();
// "V1StGXR8_Z5jdHi6B-myT"

ابزارهای مرتبط

همچنین موجود در:Python
SL
Sophie LaurentTypeScript & Full-stack Developer

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.

MW
Marcus Webbبازبین فنی

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.