JavaScript 產生的 UUID 是一個 128 位元的識別碼,以 32 個十六進位數字寫成標準的 8-4-4-4-12 格式 — 例如 f47ac10b-58cc-4372-a567-0e02b2c3d479 — 其中第 13 個十六進位數字固定為 4(版本),第 17 個則固定為 8、9、a 或 b(變體),所以 128 個位元中有 6 個是保留的,剩下 122 個可作為隨機之用。正是這 122 位元的承載量,讓 UUID v4 在任何實際應用程式產生的數量下幾乎不會碰撞。在 JavaScript 中,填入那 122 位元的安全做法是使用 Web Crypto API 的 crypto.getRandomValues,它會從瀏覽器的密碼學安全隨機數產生器取值。簡寫「UUID」代表 Universally Unique IDentifier(通用唯一識別碼),v4 變體則是 RFC 4122 及其 2024 年取代文件 RFC 9562 所定義的完全隨機版本 — 這是一種可以在任何裝置、任何地點獨立產生,不需連線至中央註冊機制的識別碼。這種無需協調的特性,正是為何這麼多 JavaScript 技術堆疊預設採用 v4 作為資料庫鍵、冪等權杖、日誌關聯 ID 與檔案名稱的原因。

UUID v4 實際上看起來是什麼樣子
每個 v4 UUID 是一個 128 位元的值,以 32 個十六進位字元呈現,分成五個區塊,長度依序為 8、4、4、4 與 12 個字元,以連字號分隔。因此標準的文字形式長度為 36 個字元 — 32 個十六進位數字加上 4 個連字號。在這 128 個位元中,正好有 6 個是非隨機的:4 個位元用於編碼版本,2 個位元用於編碼變體。由於 v4 將版本 4 儲存在第 13 個十六進位數字的高位半位元組,該數字永遠是字面字元 4。變體位元則位於第 17 個十六進位數字的高兩位元,因此該數字永遠是 8、9、a 或 b 其中之一。任何人都可以透過掃描這兩個位置來辨識 v4 UUID — 這就是整個規格的識別特徵。
辨識出版本與變體,也能讓你一眼區分 v4 與其他 UUID 版本。第 13 個十六進位數字依版本編碼為 1、3、4、5 或 7;第 17 位數字的規則則適用於所有版本,因為變體欄位是共用的。連字號分組的形狀、固定的版本半位元組,以及固定的變體半位元組,共同定義了在程式碼審查、日誌管線或資料庫欄位限制中,「看起來像 v4」真正的意涵。
為何隨機來源在 JavaScript 中至關重要
v4 UUID 中的 122 個隨機位元必須有來源,而這個來源非常重要。一段簡短的 JavaScript 程式碼可以呼叫 Math.random() 並格式化輸出,產生一個看起來像 UUID 的字串,但 Math.random 並不具備密碼學安全性:它的決定性高到足以讓看過幾次輸出的攻擊者,有時能預測後續輸出,而且其演算法在不同的引擎間也有所差異。瀏覽器安全的方式是 crypto.getRandomValues,它取自驅動 TLS 交握及其他安全關鍵 API 的同一個 CSPRNG。
這正是UUID 產生器所產生的識別碼能安全暴露於 URL、日誌與用戶端程式碼的核心原因:每個值都是從你分頁內的 crypto.getRandomValues 所產生。透過從 CSPRNG 取出 122 個位元,每個輸出在統計上都與前一個輸出獨立 — 沒有共用種子、沒有時鐘、沒有 MAC 位址,也沒有混入命名空間。這項特性讓兩個無關的服務即使在同一瞬間產生 ID,仍能確信不會發生碰撞。跳過 CSPRNG 的代價不只是理論上的:可預測的識別碼可能會被猜測、重送或在多個請求間建立關聯,這正是安全審查在拒絕基於弱隨機性所建立的識別碼時,所標記的失敗模式。
在瀏覽器中產生 UUID
不寫任何一行程式碼,就能快速產生單一 UUID 或一批 UUID 的方法,就是使用瀏覽器內的 UUID 產生器。整個流程在本地端執行,因此在發生任何網路往返之前,識別碼就已就緒。
- 開啟 UUID 產生器,輸入你想要的 UUID 數量,從 1 到 100。
- 如果你的資料庫欄位或程式碼風格需要不同的文字形式,可以切換uppercase(大寫)來將十六進位數字大寫,或切換remove hyphens(移除連字號)來移除四個分隔符號,產生一串連續的 32 字元字串。
- 點擊Generate(產生)。清單會重新整理,顯示從你瀏覽器的 CSPRNG 取得的全新 v4 UUID。
- 將游標懸停在任何一列上即可複製該單一 UUID,或使用Copy all(全部複製)一次取得整批 UUID 至剪貼簿。
由於此工具在你的分頁中執行,你可以無限重複這個步驟:每次點擊 Generate 都會產生全新的批次,而且你可以在多次執行間變更格式切換,而不會遺失先前產生的值。對於也想在實際程式碼中測試這些值的開發者來說,JavaScript Playground 是一個有用的輔助工具 — 將產生的 UUID 貼到程式碼片段中,在出貨前對你實際的驗證邏輯進行測試。
選擇輸出格式
三個切換選項決定了 UUID 產生器所回傳的文字形式。它們都不會改變底層 128 位元的值,所以選擇純粹取決於你的下游系統需要什麼。
| 切換選項 | 文字形式 | 範例 | 值相同嗎? |
|---|---|---|---|
| 預設 | 小寫,含連字號 | f47ac10b-58cc-4372-a567-0e02b2c3d479 | 是 |
| 大寫 | 大寫十六進位,含連字號 | F47AC10B-58CC-4372-A567-0E02B2C3D479 | 是 |
| 無連字號 | 小寫,無分隔符號 | f47ac10b58cc4372a5670e02b2c3d479 | 是 |
| 兩者皆是 | 大寫十六進位,無分隔符號 | F47AC10B58CC4372A5670E02B2C3D479 | 是 |
資料庫欄位通常儲存標準的 36 字元形式,因為它符合規格,但部分權杖系統、標頭值與嵌入式識別碼偏好 32 字元的無連字號形式,以節省空間或符合固定寬度欄位。如果你的技術堆疊以不區分大小寫的方式比較 UUID,大寫選項無妨;如果是以區分大小寫的方式比較,則請堅持使用小寫,才不會讓兩個看起來不同、實際上卻代表相同識別碼的字串造成困擾。
UUID v4 適用的時機
版本 4 是任何需要由兩個系統獨立產生、無需協調之識別碼的正確預設選擇 — 這正是 JavaScript 開發者經常面臨的情境。
| UUID 版本 | 位元來源 | 典型的 JavaScript 使用案例 |
|---|---|---|
| v1 | 時間戳記 + MAC 位址 | 在 JS 中很少使用;可能洩漏主機資訊 |
| v3 | 命名空間 + 名稱的 MD5 雜湊 | 從已知輸入產生的決定性 ID |
| v4 | 來自 CSPRNG 的 122 個隨機位元 | 資料庫鍵、冪等權杖、追蹤 ID、檔案名稱 |
| v5 | 命名空間 + 名稱的 SHA-1 雜湊 | 與 v3 相同,但使用更強的雜湊 |
| v7 | 毫秒時間戳記 + 隨機尾碼 | 用於索引局部性的時間排序鍵 |
實際案例與 v4 完全吻合:需要在同步前先建立記錄的分散式與離線優先系統、可防止重複 API 呼叫的冪等鍵、能貫穿整個日誌管線的關聯 ID,以及在跨服務時絕不能碰撞的物件或檔案名稱。對這些用途而言,完全沒有任何時鐘、MAC 位址或命名空間輸入,正是一項優點 — 沒有任何東西會洩漏,也沒有任何東西需要協調。
值得特別提出的一個例外是 UUIDv7。如果你的資料庫以主鍵建立索引,而且你在意索引的局部性 — 也就是新寫入的資料總是落在索引末端附近,而不是隨機分散 — 那麼 v7 的時間排序前綴會是更好的選擇。對於無序的唯一性(這是常見情況),v4 仍然是預設。
純瀏覽器產生與安全性
產生器所產生的每個 UUID,都是使用 crypto.getRandomValues 在你的瀏覽器分頁中於本地端計算。你所產生或複製的內容都不會傳送至伺服器,因此這個工具無論是用於正式環境的識別碼或內部機密都安全無虞。這項保證來自於實作本身,而不是來自於隱私承諾:此頁面從未對 UUID 後端開啟任何網路連線,剪貼簿的輸出是該值唯一會前往的地方。
為了讓碰撞的數學更具體,請考慮 122 個隨機位元。生日界限 — 即一組數字中至少出現一次重複的機率達到 50% 的門檻 — 大約是 2.71 × 10^18。將其除以每秒 10^9 個 UUID,再除以每年 31,536,000 秒,你就會得到大約 86 年的持續產生時間(每秒十億個 UUID 的速率),才會讓單一重複的可能性超過 50%。這正是分散式系統在無需跨機器協調的情況下,將 v4 UUID 視為實際上唯一的原因,也正是讓它們能在瀏覽器分頁中安全產生的特性。
對 JavaScript 開發者而言,實用的結論很簡短。任何需要無法被猜測的識別碼時,請跳過 Math.random()。在程式碼中使用 crypto.getRandomValues(),並在你需要一個比寫程式片段更快的值時,使用 UUID 產生器 — 輸出是相同的 122 位元隨機識別碼,只是不需要網路往返就能產生。如果需要驗證規格細節,標準參考文件是 RFC 4122,已由 RFC 9562 更新,其中精確定義了版本與變體位元的設定方式。
如果你正在權衡各種選項,如何使用 JavaScript 按鍵碼查詢工具對此有詳細說明。