توليد UUID v4 في JavaScript — دليل شامل
استخدم مولّد UUID v4 المجاني مباشرةً في متصفحك — لا حاجة للتثبيت.
جرّب مولّد UUID v4 أونلاين ←كل تطبيق JavaScript يحتاج في نهاية المطاف إلى معرِّفات فريدة — رموز جلسات، صفوف قواعد بيانات، مفاتيح idempotency لواجهات برمجة المدفوعات، معرِّفات ارتباط للتتبع الموزع. أبسط طريقة لتوليد UUID v4 في JavaScript اليوم هي crypto.randomUUID(): بلا اعتماديات، سطر واحد، آمن تشفيرياً. يُستخدم UUID v4 على نطاق واسع تحديداً لأنه لا يحتاج تنسيقاً بين الخدمات — يمكن للعميل والخادم توليد معرِّفات بشكل مستقل دون خطر التصادم. يغطي هذا الدليل تلك الواجهة المدمجة وحزمة uuid على npm والتحقق من الصحة — كل ذلك على Node.js 19+ والمتصفحات الحديثة. للحصول على خيار بلا كود، تُنتج أداة UUID v4 Generator على ToolDeck معرِّفات متوافقة فوراً.
- ✓crypto.randomUUID() مدمجة في المتصفحات وNode.js — بلا اعتماديات، سطر كود واحد.
- ✓UUID v4 معرِّف عشوائي بـ 128 بتاً: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx (y هي 8، 9، 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 دعم v1، v3، v5، وv7 عندما تحتاج أكثر من معرِّفات عشوائية.
- ✓للمفاتيح الأساسية في قواعد البيانات، فضِّل UUID v7 (مُرتَّب زمنياً) على v4 (عشوائي) لتقليل تشتت الفهارس.
ما هو UUID v4؟
UUID (المعرِّف الفريد عالمياً) الإصدار الرابع هو معرِّف عشوائي بـ 128 بتاً مُنسَّق كـ 32 رقماً ست عشرياً مفصولاً بأربع شرطات: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx. الرقم 4 في الموضع 15 يُحدد الإصدار. الحرف y في الموضع 20 هو أحد 8، 9، a، أو b (متغير RFC 4122). الـ 122 بتاً الباقية عشوائية. UUID v4 هو الإصدار الأكثر شيوعاً في تطبيقات 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() — الطريقة الأصلية في JavaScript
crypto.randomUUID() متاحة في Chrome 92+، وFirefox 95+، وSafari 15.4+، وNode.js 19+ (مع دعم تجريبي منذ Node.js 14.17.0 عبر globalThis.crypto). تُرجع سلسلة UUID v4 بأحرف صغيرة من 36 حرفاً. لا يلزم أي استيراد في JavaScript للمتصفح. في 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));// الطريقة 1: crypto العالمي (Node.js 19+)
const orderId = crypto.randomUUID();
console.log(orderId);
// "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
// الطريقة 2: استيراد صريح من node:crypto
import { randomUUID } from 'node:crypto';
const correlationId = randomUUID();
console.log(correlationId);
// "f7e6d5c4-b3a2-4190-8f7e-6d5c4b3a2190"تحقق من توفر crypto.randomUUID إذا كان كودك قد يعمل في متصفحات قديمة أو WebViews مضمّنة. فحص واحد بـ typeof يكفي:
function generateUUIDv4() {
// تفضيل الواجهة الأصلية عند توفرها
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
return crypto.randomUUID();
}
// احتياطي يدوي باستخدام getRandomValues (انظر القسم التالي)
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
// تعيين الإصدار (4) والمتغير (RFC 4122)
bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 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 عادي أثناء التطوير، فإن الاحتياطي باستخدام getRandomValues أعلاه يتولى تلك الحالة.توليد UUID v4 بدون مكتبة
في بعض الأحيان لا يمكنك الاعتماد على crypto.randomUUID() — ربما تستهدف WebView يحذف واجهة crypto، أو تريد فهم ما يجري داخلياً. يستخدم النهج اليدوي crypto.getRandomValues() (متاحة منذ IE 11) لملء 16 بايت ببيانات عشوائية، ثم يُطبِّق عمليتي قناع بتي لتعيين حقلي الإصدار والمتغير. هاتان العمليتان هما الفارق الوحيد بين UUID v4 وسلسلة بايتات عشوائية بحتة.
function uuidv4Manual() {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
// تعيين الإصدار: البتات 12-15 من البايت 6 = 0100 (الإصدار 4)
bytes[6] = (bytes[6] & 0x0f) | 0x40;
// تعيين المتغير: البتات 6-7 من البايت 8 = 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() لتوليد UUIDs. إنها غير آمنة تشفيرياً، فترة مخرجاتها قصيرة جداً، وبعض المحركات تُنتج تسلسلات قابلة للتنبؤ. استخدم دائماً crypto.getRandomValues() أو crypto.randomUUID().حزمة uuid على npm — دعم متعدد الإصدارات
حزمة uuid على npm كانت مكتبة UUID الأساسية لـ JavaScript قبل وجود crypto.randomUUID(). لا تزال منطقية في ثلاث حالات: تحتاج إصدارات UUID غير v4 (v1، v3، v5، v7)، أو تستهدف بيئات تشغيل أقدم من Node.js 14.17.0، أو تريد دوال الأداة validate و parse. لمجرد UUID v4 على بيئة تشغيل حديثة، الواجهة الأصلية كافية ويُفضَّل تجنب الاعتمادية.
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
// توليد دفعة لبذر قاعدة بيانات اختبار
const testAccounts = Array.from({ length: 5 }, () => ({
account_id: uuidv4(),
plan: "starter",
created_at: new Date().toISOString(),
}));
console.log(testAccounts);uuid داخلياً crypto.getRandomValues() في المتصفحات و crypto.randomBytes() في Node.js، لذا مصدر الإنتروبيا مطابق للواجهة الأصلية. الفارق هو فقط دوال الأداة الإضافية ودعم متعدد الإصدارات.إذا كنت تفضل عدم كتابة أي كود، جرّب UUID v4 Generator — يُنشئ معرِّفات v4 متوافقة مع RFC 4122 مباشرة في متصفحك بنقرة واحدة.
UUIDs حتمية — توليد UUID v5 من سلسلة نصية
UUID v4 عشوائي بطبيعته — استدعاؤه مرتين يُعطي دائماً نتائج مختلفة. أحياناً تحتاج العكس: يجب أن تُنتج نفس سلسلة المدخلات دائماً نفس UUID. هذا بالضبط ما يفعله UUID v5. يُجزِّئ UUID مساحة اسم وسلسلة مدخلات بـ SHA-1، ثم يُنسِّق النتيجة كـ UUID. نفس مساحة الاسم + نفس المدخل = نفس المخرج، في كل مرة، على كل جهاز. هذا مفيد لاشتقاق معرِّفات ثابتة من عناوين URL، عناوين البريد الإلكتروني، أو أي سلسلة تُعرِّف موردًا بالفعل.
import { v5 as uuidv5 } from 'uuid';
// مساحة اسم مدمجة لعناوين 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"
// مساحة اسم مخصصة لتطبيقك
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 نقاط ضعف معروفة في التصادم، وإن كان ذلك لا يهم كثيراً لتوليد المعرِّفات، فلا يوجد سبب لاختياره على SHA-1 عندما كلاهما متاح.
مرجع crypto.randomUUID() والواجهات ذات الصلة
الواجهة الأصلية crypto.randomUUID() لا تأخذ أي وسائط — تُرجع سلسلة نصية فحسب. استخدمها عندما تحتاج معرِّفات متوافقة مع RFC 4122 بلا اعتماديات. عندما تحتاج بايتات عشوائية خام بدلاً من سلسلة UUID منسَّقة — مثلاً لملء مصفوفة مكتوبة أو اشتقاق مفتاح — استخدم crypto.getRandomValues() مباشرة. الواجهات ذات الصلة المهمة لعمل UUID مدرجة أدناه.
تفصيل نمط regex لـ UUID v4:
التحقق من صحة UUID v4 بالتعبيرات النمطية
التحقق من صحة سلسلة UUID v4 يظهر باستمرار — أجسام طلبات API الواردة، معاملات URL، حمولات webhook. التعبير النمطي المكتوب يدوياً هو الخيار الصحيح عندما تريد صفر اعتماديات وتُتحقق من v4 فقط. إذا كنت تستخدم بالفعل حزمة uuid، فضِّل التصدير validate() الخاص بها — فهو يتعامل مع جميع إصدارات UUID وأقل عرضة للخطأ من الحفاظ على نمط مخصص. يتحقق التعبير النمطي /^[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() للفحوصات المنطقية و .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 — رقم الإصدار 1، وليس 4
console.log(isUUIDv4("550e8400-e29b-11d4-a716-446655440000")); // false
// UUID v7 — رقم الإصدار 7
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"توليد وإرفاق UUIDs من ملف واستجابة API
في الممارسة العملية، نادراً ما تستدعي crypto.randomUUID() بمعزل. نمطان يظهران باستمرار: تعيين معرِّفات للسجلات قبل كتابتها في قاعدة بيانات، وإرفاق معرِّفات ارتباط بطلبات API الصادرة لتتمكن من تتبع الطلب عبر الخدمات في سجلاتك.
قراءة ملف NDJSON → تعيين UUIDs → الكتابة مجدداً
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إرفاق معرِّف ارتباط بطلب 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: "11511" },
items: [{ sku: "WH-7291", quantity: 2, weight_kg: 1.4 }],
});توليد UUID من سطر الأوامر
لا تحتاج دائماً لسكريبت. يمكن لـ Node.js توليد UUID مباشرة من سطر الأوامر، وهو أمر مفيد لسكريبتات الشل وخطوط CI واختبار سريع. علامة -e تُقيِّم تعبيراً واحداً.
# UUID واحد node -e "console.log(crypto.randomUUID())" # 3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f # خمسة UUIDs دفعة واحدة 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
# افتح أدوات المطور في أي متصفح واكتب: crypto.randomUUID() # "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
uuidgen مثبت مسبقاً على macOS ومعظم توزيعات Linux. يُولِّد UUID v4 افتراضياً على الأنظمة الحديثة.البديل عالي الأداء — nanoid
إذا كنت تُولِّد آلاف المعرِّفات في الثانية وصيغة UUID بـ 36 حرفاً ليست شرطاً صارماً، فكِّر في nanoid. إنها أسرع بضعف من uuid.v4()، تُنتج معرِّفاً آمناً لعناوين URL بـ 21 حرفاً افتراضياً، وتزن حوالي 1 KB بعد الضغط. المخرج ليس UUID — إنه معرِّف بأبجدية مخصصة — لذا لا تستخدمه حيث يُشترط التوافق مع RFC 4122 (أعمدة UUID في قواعد البيانات، واجهات برمجة تُتحقق من صيغة UUID، معرِّفات تتبع OpenTelemetry). لكنه مناسب لمعرِّفات الارتباط الداخلية ومفاتيح مكونات React وslug عناوين URL.
npm install nanoid
import { nanoid, customAlphabet } from 'nanoid';
// افتراضي: معرِّف آمن لعناوين URL بـ 21 حرفاً (A-Za-z0-9_-)
const trackingCode = nanoid();
console.log(trackingCode);
// "V1StGXR8_Z5jdHi6B-myT"
// طول مخصص
const shortCode = nanoid(10);
console.log(shortCode);
// "IRFa-VaY2b"
// أبجدية مخصصة — أرقام فقط، 12 رقماً
const numericId = customAlphabet('0123456789', 12);
console.log(numericId());
// "839274651023"
// أبجدية مخصصة — hex فقط، 32 حرفاً (نفس إنتروبيا UUID v4 بدون شرطات)
const hexId = customAlphabet('0123456789abcdef', 32);
console.log(hexId());
// "4f8a1b2c3d7e9f0a5b6c8d1e2f3a4b5c"مخرجات الطرفية مع تظليل بناء الجملة
تصحيح أخطاء التطبيقات الثقيلة بـ UUID يعني التحديق في جدران من سلاسل hex في الطرفية. الترميز بالألوان يساعد. مكتبة chalk (أو node:util المدمج الأحدث styleText في Node.js 21.7+) تتيح تظليل UUIDs في مخرجات السجل لتبرز من النص المحيط.
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",...}توليد معرِّفات فريدة قصيرة في JavaScript
الـ 36 حرفاً لـ UUID طويلة أحياناً — slug عناوين URL وبيانات QR ورسائل SMS وبروتوكولات الأجهزة المدمجة لها قيود على الطول.
import { randomUUID } from 'node:crypto';
// 1. حذف الشرطات من UUID v4 ← سلسلة hex بـ 32 حرفاً
const hex32 = randomUUID().replaceAll('-', '');
console.log(hex32);
// "3e7f1a924b0c4d8e9f127a6b3c8d5e1f" (32 حرفاً)
// 2. ترميز Base64 لـ 16 بايت عشوائي ← سلسلة بـ 22 حرفاً (آمنة لعناوين URL)
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
const base64Id = Buffer.from(bytes)
.toString('base64url')
.replace(/=+$/, '');
console.log(base64Id);
// "Pj8akksNTY6fEnarPIvR" (22 حرفاً، 128 بتاً من الإنتروبيا)
// 3. nanoid بطول مخصص
import { nanoid } from 'nanoid';
const short12 = nanoid(12);
console.log(short12);
// "V1StGXR8_Z5j" (12 حرفاً، ~71 بتاً من الإنتروبيا)حساب احتمال التصادم: nanoid بـ 12 حرفاً (أبجدية افتراضية 64 حرفاً) يُعطي حوالي 71 بتاً من الإنتروبيا. بمعدل 1000 معرِّف في الثانية، تحتاج حوالي 116 سنة للوصول إلى احتمال تصادم بنسبة 1%. لمعظم التطبيقات، هذا أكثر من كافٍ. إذا كنت تُولِّد ملايين المعرِّفات يومياً، التزم بـ UUID الكامل أو استخدم nanoid بـ 21 حرفاً على الأقل.
UUID v7 — البديل المُرتَّب زمنياً لـ v4
UUID v7 (المُعرَّف في RFC 9562) يُضمِّن طابعاً زمنياً Unix بالمللي ثانية من 48 بتاً في المقطع الأول، متبوعاً ببتات عشوائية. النتيجة UUID يبدو مشابهاً لـ v4 لكنه يُرتَّب زمنياً. هذا يجعله خياراً أفضل من v4 للمفاتيح الأساسية في قواعد البيانات: الصفوف الجديدة تُلحق دائماً في نهاية فهرس B-tree بدلاً من مواضع عشوائية، مما يقلل تقسيم الصفحات والتشتت. في المشاريع التي أحتاج فيها معرِّفات مُرتَّبة زمنياً لجدول Postgres، أنتقل فوراً إلى v7 — فارق أداء الفهارس قابل للقياس على نطاق واسع. تُظهر أداة UUID v7 Generator على ToolDeck الطابع الزمني المُضمَّن لأي 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 من الإصدار 9.0.0 فصاعداً. إذا كنت على إصدار أقدم، شغِّل npm install uuid@latest للترقية.UUID v4 في المتصفح بدون خطوة بناء
بلا bundler، بلا npm، بلا مُترجِم. مجرد ملف HTML عادي. هذه أبسط طريقة ممكنة لتوليد UUID في JavaScript من جانب العميل. تعمل لأن crypto.randomUUID() واجهة برمجة مدمجة في المتصفح.
<!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 تجلب المكتبات. لأي شيء أكثر تعقيداً — التوليد الدفعي، التحقق من الصحة، المعرِّفات الحتمية — ستحتاج حزمة uuid أو الاحتياطي اليدوي المُبيَّن سابقاً. لكن لنموذج أولي سريع أو أداة داخلية، هذا كل ما تحتاجه.
الأخطاء الشائعة
رأيت نمط UUID باستخدام Math.random() مُنسخاً من مدونات قديمة إلى كود الإنتاج أكثر مما ينبغي. الأخطاء التي تُدخلها هذه الأنماط صامتة: لا خطأ في وقت التشغيل، فقط سلوك خاطئ بدقة يظهر لاحقاً تحت الحمل أو في مراجعات الأمان.
المشكلة: Math.random() غير آمنة تشفيرياً. مخرجاتها قابلة للتنبؤ في بعض المحركات، والإنتروبيا المنخفضة تجعل التصادمات أكثر احتمالاً بكثير من CSPRNG صحيح.
الحل: استخدم دائماً crypto.randomUUID() أو crypto.getRandomValues(). كلاهما يستخدم CSPRNG نظام التشغيل.
// آمن — يستخدم CSPRNG نظام التشغيل
const id = crypto.randomUUID();
// أو إذا احتجت احتياطياً يدوياً:
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() تُرجع hex بأحرف صغيرة، لكن UUIDs من أنظمة أخرى (قواعد بيانات، واجهات 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. في JavaScript، تغليف سلسلة UUID في كائن عن طريق الخطأ يُعطِّل فحوصات المساواة وتسلسل JSON واستعلامات قاعدة البيانات.
الحل: خزِّن UUIDs وانقلها دائماً كسلاسل عادية. إذا أرجعت مكتبة كائناً، استدعِ .toString() أو تصل إلى خاصية السلسلة فوراً.
// استخدم سلسلة فقط
const id = crypto.randomUUID();
console.log(JSON.stringify({ id }));
// {"id":"3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f"}// إنشاء غلاف غير ضروري
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 v7 عندما تحتاج معرِّفات مُرتَّبة زمنياً. احتفظ بـ UUID v4 للرموز ومعرِّفات الارتباط حيث لا يهم ترتيب الفرز.
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
لمعظم مشاريع JavaScript: استخدم crypto.randomUUID() عندما تحتاج فقط UUID v4 وبيئة التشغيل حديثة بما يكفي. انتقل إلى حزمة uuid عندما تحتاج دعم v5 (حتمي) أو v7 (مُرتَّب زمنياً). استخدم nanoid عندما يكون معرِّف قصير آمن لعناوين URL أكثر عملية من UUID بـ 36 حرفاً — لكن تذكر أن مخرجات nanoid غير متوافقة مع UUID وستفشل التحقق على أي نظام يتوقع صيغة RFC 4122.
للبديل بدون كود، جرّب UUID v4 Generator لإنشاء معرِّفات فوراً في المتصفح. لفحص UUID موجود، الصقه في UUID Decoder لرؤية إصداره ومتغيره وأي بيانات طابع زمني مُضمَّنة.
الأسئلة الشائعة
كيف أُولِّد UUID v4 في JavaScript؟
استدعِ crypto.randomUUID() في أي متصفح حديث (Chrome 92+، Firefox 95+، Safari 15.4+) أو Node.js 19+. تُرجع الدالة سلسلة بأحرف صغيرة مثل "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 Generator في /en/uuid/v4 تُنتج معرِّفات متوافقة بنقرة واحدة.
const sessionId = crypto.randomUUID(); console.log(sessionId); // "3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f"
هل crypto.randomUUID() آمنة تشفيرياً؟
نعم. تستخدم crypto.randomUUID() نفس CSPRNG (المولّد الزائف للأرقام العشوائية الآمن تشفيرياً) الذي يدعم crypto.getRandomValues(). إن الـ 122 بتاً عشوائياً في UUID v4 تجعل احتمال التصادم ضئيلاً لجميع الأغراض العملية — فأنت بحاجة لتوليد ما يقارب 2.71 كوينتيليون UUID قبل الوصول إلى احتمال 50% لتصادم واحد. تأتي الإنتروبيا من مصدر العشوائية في نظام التشغيل (/dev/urandom على Linux وBCryptGenRandom على Windows)، وليس من Math.random() الذي لا يُعدّ آمناً تشفيرياً. هذا يعني أن قيم UUID v4 آمنة للاستخدام كرموز جلسات وRCSF ومعرِّفات أخرى حساسة أمنياً. لا تستبدل أبداً مولّدات UUID المستندة إلى Math.random() في السياقات الأمنية.
هل يمكنني استخدام UUID v4 كمفتاح أساسي في قاعدة البيانات؟
يمكنك ذلك، لكن ثمة مقايضة في الأداء. UUID v4 عشوائي تماماً، لذا تتشتت فهارس B-tree بشدة لأن كل صف جديد يُدرج في موضع عشوائي من الفهرس بدلاً من نهايته. على الجداول كثيرة الكتابة، يُسبب ذلك تقسيماً مفرطاً للصفحات وإخفاقات في الكاش، مما يُدهور أداء INSERT وعمليات المسح النطاقي. إذا كانت قاعدة بياناتك تدعم ذلك (PostgreSQL وMySQL 8.0+ وSQL Server)، فإن UUID v7 (المُرتَّب زمنياً) أفضل كمفتاح أساسي لأن الصفوف الجديدة تُلحق دائماً في نهاية الفهرس. يبقى UUID v4 الخيار الصحيح لرموز الجلسات ومعاملات OAuth وأحداث إنهاء المعاملة ومعرِّفات الارتباط وأي حقل يُفضَّل فيه إخفاء وقت الإنشاء.
// UUID v4 — عشوائي، غير قابل للترتيب
const correlationId = crypto.randomUUID();
// UUID v7 — مُرتَّب زمنياً، أفضل كمفتاح أساسي في قاعدة البيانات
import { v7 as uuidv7 } from 'uuid';
const rowId = uuidv7();ما الفرق بين UUID v4 وUUID v7؟
يملأ UUID v4 الـ 122 بتاً ببيانات عشوائية — كل مقطع هو في الأساس ضوضاء. أما UUID v7 (RFC 9562، نُشر 2024) فيُشفِّر طابعاً زمنياً Unix بالمللي ثانية من 48 بتاً في المقطع الأول، و12 بتاً لدقة أقل من الميلي ثانية في المقطع الثاني، وبتات عشوائية في الباقي. كلاهما 128 بتاً إجمالاً ويستخدمان نفس صيغة 36 حرفاً مع شرطات، لذا يمكن التبديل بينهما على مستوى التخزين. UUID v7 قابل للترتيب المعجمي حسب وقت الإنشاء، مما يُبقي فهارس B-tree مضغوطة ويجعل الاستعلامات النطاقية على نوافذ زمنية فعّالة. اختر UUID v4 حين يجب ألا يكشف المعرِّف وقت إنشائه — مثلاً رموز تواجه الجمهور حيث يمكن استغلال معلومات التوقيت — واختر UUID v7 للمفاتيح الأساسية في قواعد البيانات وسجلات التدقيق وتدفقات الأحداث حيث يهم الترتيب الزمني.
كيف أتحقق من صحة سلسلة UUID v4 في JavaScript؟
اختبر مقابل التعبير النمطي /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i. الرقم الحرفي "4" في الموضع 15 (من الصفر) يؤكد رقم الإصدار؛ والحرف في الموضع 20 — أحد 8، 9، a، أو b — يُشفِّر بتات متغير RFC 4122. يرفض هذا التعبير النمطي بشكل صحيح UUID v1 وv7 وأي سلسلة مشوهة. علامة i تجعله غير حساس لحالة الأحرف، لذا تجتاز الأرقام الست عشرية الكبيرة من أنظمة أخرى التحقق دون تطبيع. إذا كنت تريد فقط معرفة ما إذا كانت سلسلة 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كيف أُولِّد معرِّفاً فريداً قصيراً في JavaScript؟
احذف الشرطات من UUID v4 للحصول على سلسلة ست عشرية بـ 32 حرفاً: crypto.randomUUID().replaceAll("-", ""). لشيء أقصر، استخدم nanoid التي تُنتج معرِّفاً آمناً لعناوين URL بـ 21 حرفاً (A–Z، a–z، 0–9، _ و-) افتراضياً مع مقاومة تصادم مماثلة لـ UUID كاملة. المقايضة واضحة: المعرِّفات الأقصر لها احتمال تصادم أعلى، لكن nanoid بـ 21 حرفاً لا يزال يوفر 126 بتاً من الإنتروبيا، وهو أكثر من كافٍ لكل تطبيق عملي تقريباً. لأجل slugs العناوين وبيانات رمز QR يمكنك الوصول لـ 10-12 حرفاً مع nanoid قبل أن يصبح احتمال التصادم مصدر قلق عند معدلات التوليد المعتادة. تجنب ترميز Base64 لـ UUID خام ثم اقتطاعه — الاقتطاع يدمر الاستقلالية الإحصائية للبتات ويجعل التصادمات أصعب في التحليل.
// سلسلة hex بـ 32 حرفاً من UUID v4
const hexId = crypto.randomUUID().replaceAll('-', '');
// "3e7f1a924b0c4d8e9f127a6b3c8d5e1f"
// معرِّف آمن لعناوين URL بـ 21 حرفاً عبر 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.