Tiếng Việt

Làm chủ toán tử nullish coalescing (??) của JavaScript để gán giá trị mặc định gọn gàng và hiệu quả hơn. Tìm hiểu sự khác biệt so với toán tử OR (||) và xem các ví dụ thực tế.

Toán tử Nullish Coalescing trong JavaScript: Hướng dẫn Toàn diện về Gán Giá trị Mặc định

Trong JavaScript, việc gán giá trị mặc định là một tác vụ phổ biến. Theo truyền thống, các nhà phát triển đã sử dụng toán tử OR (||) cho mục đích này. Tuy nhiên, toán tử nullish coalescing (??), được giới thiệu trong ECMAScript 2020, cung cấp một cách chính xác và đáng tin cậy hơn để xử lý việc gán giá trị mặc định, đặc biệt là khi làm việc với các giá trị null hoặc undefined. Hướng dẫn này sẽ đi sâu vào toán tử nullish coalescing, khám phá cú pháp, hành vi, sự khác biệt so với toán tử OR và các trường hợp sử dụng thực tế.

Nullish Coalescing là gì?

Toán tử nullish coalescing (??) là một toán tử logic trả về toán hạng bên phải của nó khi toán hạng bên trái là null hoặc undefined. Ngược lại, nó trả về toán hạng bên trái. Nói một cách đơn giản hơn, nó cung cấp một giá trị mặc định chỉ khi một biến hoàn toàn là null hoặc undefined.

Cú pháp

Cú pháp của toán tử nullish coalescing rất đơn giản:

leftOperand ?? rightOperand

Ở đây, leftOperand là biến hoặc biểu thức bạn muốn kiểm tra xem có phải là null hoặc undefined hay không, và rightOperand là giá trị mặc định bạn muốn gán nếu leftOperand thực sự là null hoặc undefined.

Ví dụ

Hãy xem xét ví dụ sau:

const username = null ?? "Guest";
console.log(username); // Output: Guest

const age = undefined ?? 25;
console.log(age); // Output: 25

const city = "London" ?? "Unknown";
console.log(city); // Output: London

Trong ví dụ này, username được gán giá trị mặc định "Guest" vì ban đầu nó là null. Tương tự, age được gán 25 vì nó bắt đầu là undefined. Tuy nhiên, city giữ lại giá trị ban đầu của nó, "London", vì nó không phải là null cũng không phải là undefined.

Giá trị Nullish và Falsy

Điều quan trọng là phải hiểu sự khác biệt giữa các giá trị nullishfalsy trong JavaScript. Một giá trị nullishnull hoặc undefined. Một giá trị falsy là một giá trị được coi là sai khi gặp trong một ngữ cảnh Boolean. Các giá trị falsy bao gồm:

Sự khác biệt chính là toán tử nullish coalescing chỉ kiểm tra null hoặc undefined, trong khi toán tử OR (||) kiểm tra bất kỳ giá trị falsy nào.

Sự khác biệt giữa ??||

Toán tử OR (||) là một toán tử OR logic trả về toán hạng bên phải nếu toán hạng bên trái là falsy. Mặc dù nó có thể được sử dụng để gán giá trị mặc định, nó có thể dẫn đến hành vi không mong muốn khi xử lý các giá trị như 0 hoặc một chuỗi rỗng.

Ví dụ: Những cạm bẫy của ||

const quantity = 0 || 10; // Chúng ta dự định mặc định là 10 nếu quantity bị thiếu
console.log(quantity); // Output: 10 (Không mong muốn!) vì 0 là falsy

const text = '' || 'Default Text'; //Chúng ta dự định một văn bản mặc định nếu text bị thiếu
console.log(text); // Output: Default Text (Không mong muốn!) vì '' là falsy

Trong ví dụ đầu tiên, chúng ta dự định gán một số lượng mặc định là 10 chỉ khi quantity bị thiếu (null hoặc undefined). Tuy nhiên, vì 0 là một giá trị falsy, toán tử OR đã gán sai giá trị mặc định. Tương tự, chuỗi rỗng làm cho văn bản mặc định được hiển thị ngay cả khi chuỗi tồn tại (nhưng rỗng).

Sử dụng ?? để tăng độ chính xác

Hãy viết lại ví dụ trước bằng cách sử dụng toán tử nullish coalescing:

const quantity = 0 ?? 10;
console.log(quantity); // Output: 0 (Chính xác!)

const text = '' ?? 'Default Text';
console.log(text); // Output: '' (Chính xác!)

Bây giờ, kết quả đầu ra đã như mong đợi. Toán tử nullish coalescing chỉ kiểm tra null hoặc undefined, vì vậy 0'' được coi là các giá trị hợp lệ và giá trị ban đầu của chúng được giữ lại.

Các trường hợp sử dụng Nullish Coalescing

Toán tử nullish coalescing hữu ích trong nhiều tình huống khác nhau khi bạn cần cung cấp giá trị mặc định chỉ khi một biến hoàn toàn là null hoặc undefined. Dưới đây là một số trường hợp sử dụng phổ biến:

1. Xử lý tham số tùy chọn của hàm

Khi định nghĩa một hàm với các tham số tùy chọn, bạn có thể sử dụng toán tử nullish coalescing để cung cấp giá trị mặc định nếu các tham số không được cung cấp.

function greet(name, greeting) {
  const userName = name ?? "User";
  const userGreeting = greeting ?? "Hello";
  console.log(`${userGreeting}, ${userName}!`);
}

greet(); // Output: Hello, User!
greet("Alice"); // Output: Hello, Alice!
greet("Bob", "Greetings"); // Output: Greetings, Bob!

2. Thiết lập các tùy chọn cấu hình mặc định

Khi làm việc với các đối tượng cấu hình, bạn có thể sử dụng toán tử nullish coalescing để đảm bảo rằng các giá trị mặc định được sử dụng nếu một số tùy chọn cấu hình không được chỉ định.

const config = {
  timeout: 5000,
  retries: 3
};

function fetchData(options) {
  const timeout = options.timeout ?? 10000; // Thời gian chờ mặc định là 10 giây
  const retries = options.retries ?? 5; // Mặc định 5 lần thử lại
  console.log(`Timeout: ${timeout}, Retries: ${retries}`);
}

fetchData(config); // Output: Timeout: 5000, Retries: 3
fetchData({}); // Output: Timeout: 10000, Retries: 5
fetchData({timeout:null, retries: undefined}); // Output: Timeout: 10000, Retries: 5

3. Truy cập các thuộc tính đối tượng lồng nhau

Khi truy cập các thuộc tính của các đối tượng lồng nhau, toán tử nullish coalescing có thể được kết hợp với optional chaining (?.) để cung cấp giá trị mặc định nếu bất kỳ thuộc tính trung gian nào là null hoặc undefined.

const user = {
  profile: {
    address: {
      city: "New York"
    }
  }
};

const cityName = user?.profile?.address?.city ?? "Unknown";
console.log(cityName); // Output: New York

const unknownUser = {};
const unknownCityName = unknownUser?.profile?.address?.city ?? "Unknown";
console.log(unknownCityName); // Output: Unknown

4. Làm việc với API và dữ liệu bên ngoài

Khi lấy dữ liệu từ các API hoặc các nguồn bên ngoài, toán tử nullish coalescing có thể được sử dụng để cung cấp các giá trị mặc định nếu một số trường dữ liệu bị thiếu hoặc có giá trị null hoặc undefined. Hãy xem xét việc lấy dữ liệu người dùng từ các khu vực khác nhau. Giả sử một số khu vực có thể không bao gồm trường `country` trong dữ liệu người dùng của họ.

async function getUserData(userId) {
  try {
    const response = await fetch(`https://api.example.com/users/${userId}`);
    const data = await response.json();
    const country = data.country ?? "Unknown Country";
    const timezone = data.timezone ?? "UTC";
    console.log(`User is from: ${country}, Timezone: ${timezone}`);
  } catch (error) {
    console.error("Error fetching user data:", error);
  }
}

// Mô phỏng các phản hồi API khác nhau:
const userWithCountry = { name: "John", country: "USA", timezone: "EST" };
const userWithoutCountry = { name: "Jane", timezone: "GMT" };

// Để kiểm tra điều này, bạn sẽ cần một API thực tế hoặc mock fetch.
// Với mục đích trình diễn, chúng ta hãy mô phỏng các phản hồi:
global.fetch = async (url) => {
    if (url.includes("123")) {
        return { json: async () => userWithCountry };
    } else if (url.includes("456")) {
        return { json: async () => userWithoutCountry };
    }
    throw new Error("Unexpected URL");
};

getUserData(123); // Output: User is from: USA, Timezone: EST
getUserData(456); // Output: User is from: Unknown Country, Timezone: GMT

Độ ưu tiên của toán tử

Toán tử nullish coalescing có độ ưu tiên tương đối thấp. Nó thấp hơn các toán tử OR (||) và AND (&&). Do đó, khi kết hợp toán tử nullish coalescing với các toán tử logic khác, điều cần thiết là sử dụng dấu ngoặc đơn để xác định rõ ràng thứ tự các phép toán. Nếu không làm như vậy có thể dẫn đến lỗi cú pháp hoặc hành vi không mong muốn.

Ví dụ: Sử dụng dấu ngoặc đơn để rõ ràng

// Không có dấu ngoặc đơn (SyntaxError)
// const result = false || null ?? "Default"; // SyntaxError: Unexpected token '??'

// Có dấu ngoặc đơn (Chính xác)
const result = false || (null ?? "Default");
console.log(result); // Output: Default

const anotherResult = (false || null) ?? "Default";
console.log(anotherResult); // Output: null

Trong ví dụ đầu tiên, việc thiếu dấu ngoặc đơn dẫn đến SyntaxError vì công cụ JavaScript không thể xác định thứ tự các phép toán dự định. Bằng cách thêm dấu ngoặc đơn, chúng ta đã chỉ rõ cho công cụ đánh giá toán tử nullish coalescing trước. Ví dụ thứ hai là hợp lệ; tuy nhiên, đầu ra khác nhau vì biểu thức || được đánh giá trước.

Khả năng tương thích với trình duyệt

Toán tử nullish coalescing (??) là một tính năng tương đối mới, vì vậy điều quan trọng là phải xem xét khả năng tương thích của trình duyệt, đặc biệt nếu bạn đang nhắm mục tiêu đến các trình duyệt cũ hơn. Hầu hết các trình duyệt hiện đại đều hỗ trợ toán tử nullish coalescing, bao gồm:

Nếu bạn cần hỗ trợ các trình duyệt cũ hơn, bạn có thể sử dụng một trình chuyển mã như Babel để chuyển đổi mã của mình sang một phiên bản JavaScript tương thích. Babel sẽ chuyển đổi toán tử ?? thành mã JavaScript tương đương hoạt động trong các môi trường cũ hơn.

Các phương pháp tốt nhất

Dưới đây là một số phương pháp tốt nhất để sử dụng toán tử nullish coalescing một cách hiệu quả:

Những lưu ý toàn cục

Khi phát triển cho đối tượng người dùng toàn cầu, hãy xem xét các điểm sau liên quan đến việc gán giá trị mặc định:

Ví dụ: Bản địa hóa với Nullish Coalescing

Giả sử bạn muốn hiển thị một thông điệp chào mừng mặc định bằng các ngôn ngữ khác nhau dựa trên ngôn ngữ của người dùng. Bạn có thể sử dụng toán tử nullish coalescing để cung cấp một thông điệp mặc định nếu không có thông điệp đã được bản địa hóa.

function getWelcomeMessage(locale) {
  const localizedMessages = {
    en: "Welcome!",
    fr: "Bienvenue !",
    de: "Willkommen!"
  };

  const message = localizedMessages[locale] ?? "Welcome!"; // Mặc định là tiếng Anh nếu không tìm thấy ngôn ngữ
  return message;
}

console.log(getWelcomeMessage("fr")); // Output: Bienvenue !
console.log(getWelcomeMessage("es")); // Output: Welcome! (Mặc định là tiếng Anh)

Kết luận

Toán tử nullish coalescing (??) là một sự bổ sung quý giá cho ngôn ngữ JavaScript. Nó cung cấp một cách gán giá trị mặc định chính xác và đáng tin cậy hơn so với toán tử OR (||), đặc biệt khi xử lý các giá trị như 0 hoặc chuỗi rỗng. Bằng cách hiểu cú pháp, hành vi và các trường hợp sử dụng của nó, bạn có thể viết mã sạch hơn, dễ bảo trì hơn và xử lý chính xác việc gán giá trị mặc định. Hãy nhớ xem xét khả năng tương thích của trình duyệt, độ ưu tiên của toán tử và các yếu tố toàn cục khi sử dụng toán tử nullish coalescing trong các dự án của bạn.

Bằng cách tuân theo các phương pháp tốt nhất được nêu trong hướng dẫn này, bạn có thể tận dụng hiệu quả toán tử nullish coalescing để cải thiện chất lượng và độ tin cậy của mã JavaScript của mình, làm cho nó trở nên mạnh mẽ và dễ hiểu hơn. Hãy nhớ luôn ưu tiên sự rõ ràng và khả năng bảo trì trong mã của bạn, và toán tử nullish coalescing có thể là một công cụ mạnh mẽ để đạt được những mục tiêu này.