??|| 搞混,線上使用者頭像全掛了

問題場景

上週五快下班,客服群突然炸了:

「好多使用者頭像顯示空白!」
「不是全部,大概 30% 的帳號頭像沒了」

查前端日誌,頭像 API 回傳正常,url 欄位有值。再看渲染層程式碼:

js 代碼解讀複製代碼const avatarUrl = user.avatar?.url || '/default-avatar.png'

邏輯看似沒毛病:有頭像用頭像,沒有就用預設圖。但詭異的是,有頭像的使用者也顯示了預設圖

原因分析

問題出在 || 運算子的「激進」行為上。

|| 會把所有假值(falsy) 都當成「沒有」來對待。JavaScript 中的假值包括:

值類型''空字串0數字零false布林假nullundefined未定義NaN非數字排查後發現,這批頭像異常的使用者的 url 值剛好是 空字串 '' — 頭像服務在某些情況下會回傳 url: ""(代表使用者上傳過頭像但處理失敗)。

js 代碼解讀複製代碼// 實際資料
user.avatar = { url: '' }  // 空字串,但 ≠ 沒頭像

// 執行邏輯
const avatarUrl = '' || '/default-avatar.png'
// → 空字串是假值,被 || 吞掉,回傳預設圖 ❌

使用者明明上傳過頭像(資料庫有紀錄),只是因為圖片處理失敗回傳了空字串,就被 || 強制替換成預設圖——這就成了「有頭像但顯示預設」的 bug。

解決方案

方案一:改用 ??(空值合併運算子)

js 代碼解讀複製代碼const avatarUrl = user.avatar?.url ?? '/default-avatar.png'

?? 只會在左操作數為 nullundefined 時才取右側值。''0false 都會原樣保留。

注意: ?? 不能與 &&|| 混用不加括號:

js 代碼解讀複製代碼// ❌ 語法錯誤
const a = b ?? c || d

// ✅ 正確寫法
const a = (b ?? c) || d

方案二:顯式判斷

js 代碼解讀複製代碼const avatarUrl = user.avatar?.url && user.avatar.url.length > 0
  ? user.avatar.url
  : '/default-avatar.png'

更保險,但囉嗦。

方案三:後端統一語意

後端對 url 欄位做約束:沒有頭像 → 不回傳欄位或回傳 null;有頭像(包括處理失敗)都正確定義。前端只信任 ??

深入:還有哪些地方容易踩?

場景 1:分數/數值 0

js 代碼解讀複製代碼// 使用者完成了 0 道題
const count = data.completedCount || '無資料'
// 0 被 || 吞掉,顯示「無資料」❌
const count = data.completedCount ?? '無資料'  // ✅ 顯示 0

場景 2:CSS class 拼接

js 代碼解讀複製代碼// 某個狀態的 className 可能是空字串 ''
const cls = statusClass || 'default-status'
// 空字串時被覆蓋 ❌
const cls = statusClass ?? 'default-status'  // ✅

場景 3:函式預設參數

js 代碼解讀複製代碼function setTheme(color = '#333') { ... }

setTheme('')   // '' 是假值嗎?不,函式預設參數只對 undefined 生效
// → 傳入 '' 不會觸發預設值,color = ''

函式預設參數的行為類似 ??,只對 undefined 生效。很多人誤以為它和 || 一樣。

要點總結

運算子觸發替換的條件適用場景??``null / undefined後端可能缺失的欄位、可選鏈取值`所有假值兜底預設值(明確想過濾空字串/0)函式預設參數僅 undefined參數缺省傳值一句話黃金法則:

當你要表達「沒有這個資料就用預設值」時,99% 的場景應該用 ??;只有 1% 的場景(如使用者輸入為空時填預設文案)才刻意用 ||

修完這個 bug 後的復盤會上,全組把 ESLint 加了一條規則:

json 代碼解讀複製代碼// .eslintrc
{
  "rules": {
    "no-unneeded-ternary": "error",
    "@typescript-eslint/prefer-nullish-coalescing": "error"
  }
}

並在 code review checklist 裡寫死了一條:「看到 || 接變數,先想想是不是應該用 ??

從此,頭像空白 bug 再沒出現過。


原文出處:https://juejin.cn/post/7655657102968438811


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝13   💬2   ❤️1
573
🥈
我愛JS
📝1   ❤️1
71
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登