自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

前端問答:JavaScript 中的 "??" 和 "||" 有啥不同

開發(fā)
一開始看,??(空值合并運算符)和 ||(邏輯或運算符)似乎都能達到相同的效果,但其實它們背后的邏輯完全不同,適用的場景也不一樣。今天我們就來聊聊這兩者的區(qū)別,幫你快速上手,避免掉坑!

在 JavaScript 開發(fā)中,很多小伙伴都會遇到一個場景,就是要給變量設(shè)置一個默認(rèn)值,比如當(dāng)變量沒有有效值時,使用一個備用值。這個時候,可能有兩個操作符會讓你感到困惑:??(空值合并運算符)和 ||(邏輯或運算符)。一開始看,它們似乎都能達到相同的效果,但其實它們背后的邏輯完全不同,適用的場景也不一樣。今天我們就來聊聊這兩者的區(qū)別,幫你快速上手,避免掉坑!

一、"||" 是怎么工作的?—— 就像找備胎一樣!

|| 就好像是在說:“如果這個不行,就換另一個?!彼木唧w作用是檢查左邊的值(第一個計劃),如果左邊這個值是 “假”(也就是不靠譜、不能用的意思),它就會去看右邊的值(第二個計劃),并返回右邊的值。

舉個例子來理解一下:

let result = value1 || value2;

這段代碼就是在說:“如果 value1 能用,就用 value1;如果 value1 不行,那就用 value2 吧!”那問題來了,什么情況下 value1 會不行呢?

1. 什么是 "假值"?

在 JavaScript 里,有一些特殊的值會被認(rèn)為是“假”的,像這些:

  • false(假)
  • 0(零)
  • ""(空字符串)
  • null(表示空)
  • undefined(未定義)
  • NaN(非數(shù)字)

這些值都被認(rèn)為是不能用的“假值”。如果你遇到這些值,|| 操作符就會幫你返回后面的備用計劃。

2. 舉個栗子??:

let username = "" || "游客"; // 返回 "游客"
let score = 0 || 10;          // 返回 10

在上面的例子里,""(空字符串)和 0 都是“假值”,所以 JavaScript 會忽略它們,直接選擇后面的“游客”和 10 作為返回值。

3. 那什么時候用 "||" 呢?

|| 的最佳使用場景就是當(dāng)你不確定一個值是否靠譜的時候,你可以為它準(zhǔn)備一個備用值。就像生活中你遇到的兩手準(zhǔn)備:如果第一種方案失敗了,立刻執(zhí)行第二種。

比如你想讓用戶輸入他們的名字,但如果用戶沒有輸入名字,你就讓系統(tǒng)自動叫他們“游客”。用 || 來實現(xiàn)這個需求簡直再好不過了:

function greetUser(name) {
  let username = name || "游客";
  console.log(`你好, ${username}!`);
}

greetUser("");  // 輸出: 你好, 游客!
greetUser("Alice");  // 輸出: 你好, Alice!

在這個例子里,如果用戶沒有輸入名字(比如空字符串 ""),我們就用 || 返回一個默認(rèn)值“游客”。但如果用戶輸入了名字(比如 “Alice”),我們就用這個名字打招呼。

二、JavaScript 中的"??"操作符:只關(guān)心空值,別搞混了!

JavaScript 里的??(空值合并運算符)看起來和我們之前聊過的||有點像,但它其實更“挑剔”!如果說||是遇到假值就找備胎,那么??只會在 null 和 undefined 出現(xiàn)時才出手救場。今天咱們就來深入了解一下這個 ECMAScript 2020 (ES11) 中的新工具。

1. "??" 是怎么工作的?—— 只處理“真正”的空值

?? 操作符的工作方式是:當(dāng)左邊的值是 null 或 undefined 時,才返回右邊的備用值。像 0、false、"" 這些“假值”,在??眼里都是 有效值,它們不會觸發(fā)備用計劃。

語法很簡單:

let result = value1 ?? value2;

意思是:如果 value1 是 null 或 undefined,那就返回 value2;否則就直接用 value1。

2. 舉個例子??:

let username = "" ?? "游客"; // 返回 ""
let score = 0 ?? 10;          // 返回 0

在這兩個例子中,空字符串 "" 和 0 雖然是“假值”,但因為它們不是 null 或 undefined,?? 不會認(rèn)為它們無效,所以直接返回它們本身。這樣就避免了 || 操作符那種“誤判”的情況——如果你真的想用 0 或 "" 作為有效值,?? 就非常合適。

3. 什么時候用"??"?

?? 非常適合在你 只想處理null或undefined 的場景下使用。比方說,你希望某個變量可以是 0 或 false 這樣的值,而不想讓它們觸發(fā)默認(rèn)值。來看個小例子:

function getScore(score) {
  return score ?? 10;
}

console.log(getScore(0));    // 輸出: 0
console.log(getScore(null)); // 輸出: 10

在這個例子里,score 可以是 0,也可以是 null。如果傳入 0,?? 不會把它當(dāng)成空值,而是直接返回 0。但如果 score 是 null,它就會返回默認(rèn)值 10。這種行為對于某些場景非常有用,比如分?jǐn)?shù)為 0 的時候你不希望它被誤當(dāng)成無效值。

三、?? 和 || 的關(guān)鍵區(qū)別:用錯容易踩坑哦!

在 JavaScript 里,??(空值合并運算符)和 ||(邏輯或運算符)都是用來設(shè)置默認(rèn)值的利器,初學(xué)者可能覺得它們差不多,但其實它們的行為有很大不同。為了避免代碼里的坑,我們必須清楚兩者的使用場景和差異。

1. "Falsy" vs. "Nullish":誰才是真的空?

||:它的邏輯是,遇到任何“假值”(falsy)就會返回備用值。這些“假值”包括:

  • false
  • 0
  • ""(空字符串)
  • null
  • undefined
  • NaN(非數(shù)字)

只要值是這些“假值”,|| 就會觸發(fā)備用值。

??:相比之下,?? 只關(guān)注 null 和undefined。也就是說,像 0、false 和 "" 這些雖然看似“假”的值,但在 ?? 眼中是有效的,不會觸發(fā)備用值。

2. 使用場景:該選誰?

  • 使用 ||:當(dāng)你想對所有“假值”都提供一個備用方案時,比如 false、0 或空字符串。這種情況下,|| 是你最好的選擇。
  • 使用 ??:如果你只想處理 null 和 undefined,而對 0、false 這些值保留,那么 ?? 更適合你。

3. 舉例對比:看代碼更直觀

let value1 = 0 || 5;    // value1 是 5
let value2 = 0 ?? 5;    // value2 是 0

let value3 = null || "默認(rèn)值";  // value3 是 "默認(rèn)值"
let value4 = null ?? "默認(rèn)值";  // value4 是 "默認(rèn)值"

在第一個例子中,value1 變成了 5,因為 0 被 || 認(rèn)為是“假值”。而在 ?? 的情況下,value2 保持為 0,因為 0 并不是 null 或 undefined,所以不會觸發(fā)備用值。

第二個例子里,null 在兩種操作符中都觸發(fā)了備用值,結(jié)果一樣。

4. 潛在的 Bug:小心別踩坑!

誤用 || 會導(dǎo)致一些你沒料到的問題,特別是當(dāng) 0、false 或 "" 是有效值時。來看個例子:

function getDiscountedPrice(price) {
  return price || 100;  // 這里會返回 100,即使 price 是 0
}

console.log(getDiscountedPrice(0));  // 輸出: 100(錯誤)

這里的邏輯會導(dǎo)致問題,因為 0 是一個有效的價格,但由于 || 把它當(dāng)作“假值”,最終返回了備用值 100。解決方案就是用 ??,這樣 0 就不會被誤判了:

function getDiscountedPrice(price) {
  return price ?? 100;  // 這里會正確返回 0
}

console.log(getDiscountedPrice(0));  // 輸出: 0(正確)

5. 短路求值:誰先說了算?

|| 和 ?? 都使用了 短路求值,意思是如果左邊的值能決定結(jié)果,右邊的值就不會被計算。但兩者的判斷標(biāo)準(zhǔn)不同——|| 會在遇到任意“假值”時短路,而 ?? 只會在 null 或 undefined 時短路。

6.總結(jié):怎么選?

  • 如果你需要處理所有的“假值”(包括 0、false、""),就用 ||。
  • 如果你只關(guān)心 null 和 undefined,而 0、false 這些值也是有效輸入,那就用 ??。

四、結(jié)合 || 和 ??:多重保險,讓代碼更健壯!

有時候,你可能會遇到更復(fù)雜的場景,既要處理 null 和 undefined,又需要對其他“假值”如 0、false、"" 做特殊處理。這種情況下,我們可以把 || 和 ?? 結(jié)合起來,打造一個更加全面的“多重保險”邏輯。

1. 為什么要同時用 || 和 ???

?? 負(fù)責(zé)處理 null 和 **undefined**,而 || 可以處理 所有“假值”(如 0、false、空字符串等)。有些情況下,你可能希望 null 和 undefined 返回默認(rèn)值,而對于其他“假值”則使用不同的邏輯處理。

來看個例子:

let result = (value ?? defaultValue) || fallbackValue;

在這段代碼中,我們做了兩步處理:

  • value ?? defaultValue:首先,?? 檢查 value 是否為 null 或 undefined。如果是,那么返回 defaultValue;如果不是,則直接返回 value。
  • || fallbackValue:接下來,結(jié)果再經(jīng)過 ||,如果這個結(jié)果是“假值”(例如 0、false、空字符串等),就返回 fallbackValue。

2. 舉個栗子

假設(shè)你在處理一個分?jǐn)?shù)系統(tǒng),null 或 undefined 的時候要用默認(rèn)分?jǐn)?shù),但同時如果分?jǐn)?shù)是 0 也不能直接忽略,需要特殊處理。我們可以這樣寫:

function getFinalScore(score) {
  return (score ?? 50) || "分?jǐn)?shù)無效";
}

console.log(getFinalScore(null));  // 輸出: 50(null 被 `??` 處理)
console.log(getFinalScore(0));     // 輸出: "分?jǐn)?shù)無效"(0 被 `||` 處理)
console.log(getFinalScore(80));    // 輸出: 80(有效分?jǐn)?shù))
  • null 的情況:score 是 null 時,?? 返回默認(rèn)值 50,|| 不會再觸發(fā)。
  • 0 的情況:score 是 0 時,?? 不起作用,|| 將 0 視為“假值”,返回 "分?jǐn)?shù)無效"。
  • 有效分?jǐn)?shù)的情況:score 是 80 時,直接返回 80。

3. 什么時候使用這種組合?

這種組合特別適合需要處理復(fù)雜邏輯的場景,比如:

  • null 或 undefined 的時候,返回一個默認(rèn)值;
  • 其他“假值”(如 0、false)也需要單獨處理,避免被誤認(rèn)為無效。

結(jié)束

在 JavaScript 開發(fā)中,?? 和 || 絕對是處理默認(rèn)值的利器,雖然它們看上去很像,但實際應(yīng)用中卻有明顯區(qū)別。|| 會把很多值當(dāng)作“假值”,包括 0、false、空字符串等;而 ?? 只關(guān)心 null 和 undefined。因此,合理選擇這兩個運算符,能讓你避免不必要的 Bug,尤其是在處理特殊值的時候。

責(zé)任編輯:趙寧寧 來源: 前端達人
相關(guān)推薦

2010-08-17 15:21:17

IEFirefoxHTML

2019-10-22 11:12:46

臺式機筆記本顯卡

2021-12-06 15:35:01

CSS前端開發(fā)

2024-05-11 08:20:23

2021-01-07 14:20:55

JavaGC

2010-09-10 10:20:51

DIVSpan

2013-02-28 20:28:19

Office 365Office 201微軟

2020-08-02 23:20:36

JavaScriptmap()forEach()

2021-11-16 07:52:24

前端技術(shù)編程

2017-01-13 16:26:56

開發(fā)

2023-10-12 07:35:45

面試線程通信

2022-09-23 10:25:00

VueReact

2020-10-19 13:03:16

Java 8接口抽象類

2023-01-06 10:52:30

SQL索引存儲

2022-01-17 10:07:05

PodmanDocker容器

2015-01-19 13:33:44

KubernetesMesos計算集群

2010-12-23 13:56:55

SharePointIntranet

2021-04-19 09:27:03

Java線程操作系統(tǒng)

2022-05-18 10:26:01

藍牙WiFi

2018-01-05 09:43:54

ROMRAM存儲
點贊
收藏

51CTO技術(shù)棧公眾號