Bạn đã bao giờ gặp phải tình huống code JavaScript trả về những kết quả không như mong đợi chỉ vì sử dụng toán tử sai chưa? Trong lập trình JavaScript, việc lựa chọn đúng toán tử để xử lý dữ liệu không chỉ giúp tránh được những lỗi không đáng có mà còn nâng cao hiệu quả và độ chính xác của code.

Toán tử Logical OR (||) và toán tử Nullish Coalescing (??) là hai toán tử tưởng chừng tương tự nhau nhưng lại có những điểm khác biệt rất quan trọng. Bạn có chắc mình đang sử dụng đúng cách hai toán tử này? Hãy cùng codetuthub tìm hiểu rõ hơn để biết khi nào thì nên dùng toán tử nào thông qua các ví dụ thực tế dưới đây.

1. Toán tử Logical OR (||)

Toán tử Logical OR (||) là một toán tử logic quen thuộc trong nhiều ngôn ngữ lập trình. Trong JavaScript, nó không chỉ được sử dụng cho các biểu thức boolean mà còn có thể được dùng để gán giá trị mặc định. Khi được sử dụng trong ngữ cảnh này, toán tử || trả về:

  • Giá trị của toán hạng bên trái nếu nó là một giá trị truthy.
  • Giá trị của toán hạng bên phải nếu toán hạng bên trái là một giá trị falsy.

Các giá trị falsy trong JavaScript bao gồm:

  • false
  • null
  • undefined
  • 0 (số không)
  • NaN (Not a Number)
  • "" (chuỗi rỗng)

Hãy xem một vài ví dụ:

js
let username = "";
let defaultUsername = username || "Guest";
console.log(defaultUsername); // Kết quả: "Guest"

let count = 0;
let displayCount = count || 1;
console.log(displayCount); // Kết quả: 1

let isAdmin = null;
let role = isAdmin || "user";
console.log(role); // Kết quả: "user"

Trong các ví dụ trên, toán tử || hoạt động như mong đợi khi chúng ta muốn gán một giá trị mặc định cho các trường hợp null hoặc undefined. Tuy nhiên, vấn đề nảy sinh khi chúng ta muốn coi các giá trị falsy khác như 0 hoặc "" là các giá trị hợp lệ chứ không phải là dấu hiệu của việc thiếu giá trị.

Ví dụ:

js
let a = 0;
let b = 10;

let value = a || b;
console.log(value); // Kết quả: 10

Trong ví dụ trên, a bằng 0 là falsy, nên toán tử || sẽ trả về giá trị b10.

2. Toán tử Nullish Coalescing (??)

Toán tử Nullish Coalescing (??) được giới thiệu trong ECMAScript 2020 để giải quyết hạn chế của toán tử ||. Toán tử ?? chỉ xem xét hai giá trị là nullish:

  • null
  • undefined

Khi được sử dụng, toán tử ?? trả về:

  • Giá trị của toán hạng bên trái nếu nó không phải là null hoặc undefined.
  • Giá trị của toán hạng bên phải nếu toán hạng bên trái là null hoặc undefined.

Hãy xem lại các ví dụ tương tự với toán tử ??:

js
let username = "";
let defaultUsername = username ?? "Guest";
console.log(defaultUsername); // Kết quả: ""

let count = 0;
let displayCount = count ?? 1;
console.log(displayCount); // Kết quả: 0

let isAdmin = null;
let role = isAdmin ?? "user";
console.log(role); // Kết quả: "user"

Như bạn có thể thấy, toán tử ?? hoạt động khác biệt so với || trong trường hợp chuỗi rỗng ("") và số không (0). Nó chỉ thay thế giá trị khi giá trị bên trái thực sự là null hoặc undefined.

Ví dụ:

js
let a = 0;
let b = 10;

let value = a ?? b;
console.log(value); // Kết quả: 0

Trong trường hợp này, a bằng 0, dù là falsy nhưng không phải là null hay undefined, nên toán tử ?? sẽ trả về giá trị của a0.

3. Sự khác biệt chính giữa toán tử ||??

3.1. Xử lý giá trị falsy:

  • Toán tử || trả về giá trị thứ hai khi giá trị đầu tiên là bất kỳ giá trị falsy nào (false, 0, NaN, "", null, undefined).
  • Toán tử ?? chỉ trả về giá trị thứ hai khi giá trị đầu tiên là null hoặc undefined. Các giá trị falsy khác như false, 0"" đều được coi là hợp lệ.

3.2. Tình huống sử dụng:

  • Dùng toán tử || khi bạn muốn thay thế tất cả các giá trị falsy bằng một giá trị mặc định nào đó.
  • Dùng toán tử ?? khi bạn muốn xử lý đặc biệt các giá trị null hoặc undefined và giữ nguyên các giá trị falsy khác như 0, false, hoặc "".

3.3. Các ví dụ so sánh:

js
// Ví dụ với toán tử || (Logical OR)
let foo = 0;
let bar = "Hello";

console.log(foo || bar);  // Kết quả: "Hello" (do 0 là falsy)

// Ví dụ với toán tử ?? (Nullish Coalescing)
let foo2 = 0;
let bar2 = "Hello";

console.log(foo2 ?? bar2);  // Kết quả: 0 (do 0 không phải null hay undefined)

Trong ví dụ đầu tiên, toán tử || trả về "Hello" vì giá trị đầu tiên 0 là falsy. Trong ví dụ thứ hai, toán tử ?? trả về 00 không phải là null hay undefined.

4. Khi nào nên sử dụng toán tử nào?

Sự lựa chọn giữa ||?? phụ thuộc vào ngữ cảnh cụ thể và logic mà bạn muốn triển khai:

4.1. Sử dụng || khi:

  • Bạn muốn cung cấp một giá trị mặc định cho bất kỳ giá trị falsy nào, bao gồm null, undefined, 0, "", NaN, và false.
  • Điều này thường hữu ích khi bạn muốn đảm bảo một biến luôn có một giá trị "truthy", ví dụ như trong cấu hình hiển thị, chuỗi đầu ra hoặc các giá trị cần kiểm tra điều kiện.

4.2. Sử dụng ?? khi:

  • Bạn chỉ muốn cung cấp một giá trị mặc định khi giá trị ban đầu là null hoặc undefined.
  • Điều này rất hữu ích khi các giá trị falsy khác như 0, false hoặc "" là các giá trị hợp lệ và bạn không muốn chúng bị thay thế.

4.3. Ví dụ thực tế:

Giả sử bạn đang lấy dữ liệu cấu hình từ một API. Trường timeout có thể có giá trị là một số (tính bằng mili giây), hoặc có thể bị thiếu (trả về null hoặc undefined). Nếu timeout0, điều đó có nghĩa là không có thời gian chờ. Trong trường hợp này, bạn nên sử dụng ?? để cung cấp một giá trị mặc định nếu timeout thực sự bị thiếu:

js
const configFromApi = {
  apiUrl: "https://api.example.com",
  timeout: 0 // Thời gian chờ là 0 mili giây (không có timeout)
};

const timeoutValue = configFromApi.timeout ?? 5000;
console.log(`Timeout value: ${timeoutValue}`); // Kết quả: Timeout value: 0

const anotherConfig = {
  apiUrl: "https://api.example.com"
};

const anotherTimeoutValue = anotherConfig.timeout ?? 5000;
console.log(`Another timeout value: ${anotherTimeoutValue}`); // Kết quả: Another timeout value: 5000

Nếu chúng ta sử dụng || trong ví dụ trên, giá trị timeout0 sẽ bị coi là falsy và bị thay thế bằng 5000, dẫn đến hành vi không chính xác.

Kết luận

Toán tử Logical OR (||) và Nullish Coalescing (??) đều là những công cụ hữu ích trong việc xử lý giá trị mặc định trong JavaScript. Tuy nhiên, chúng có mục đích sử dụng khác nhau:

  • Dùng || khi bạn muốn thay thế bất kỳ giá trị falsy nào bằng một giá trị khác.
  • Dùng ?? khi bạn chỉ muốn thay thế giá trị nếu nó là null hoặc undefined, và vẫn chấp nhận các giá trị falsy hợp lệ như 0, false, hoặc "".

Việc lựa chọn đúng toán tử trong từng ngữ cảnh không chỉ giúp code của bạn chính xác hơn mà còn tránh được các lỗi logic tiềm ẩn trong ứng dụng. Hãy luôn đặt câu hỏi: "Giá trị mình đang xử lý có thể là hợp lệ dù là falsy không?" — nếu có, hãy cân nhắc dùng ?? thay vì ||.

Chúc bạn viết JavaScript ngày càng chuẩn hơn cùng codetuthub! và sử dụng hai toán tử này một cách chính xác và hiệu quả trong các dự án JavaScript của bạn!