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ị nullish và falsy trong JavaScript. Một giá trị nullish là null
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:
null
undefined
0
(số không)NaN
(Not a Number)''
(chuỗi rỗng)false
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 ??
và ||
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
và ''
đượ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:
- Chrome 80+
- Firefox 72+
- Safari 13.1+
- Edge 80+
- Node.js 14+
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ả:
- Sử dụng
??
cho các kiểm tra nullish: Sử dụng toán tử nullish coalescing (??
) khi bạn muốn cung cấp một giá trị mặc định chỉ khi một biến lànull
hoặcundefined
. - Sử dụng dấu ngoặc đơn cho các biểu thức phức tạp: Khi kết hợp toán tử nullish coalescing với các toán tử logic khác, hãy sử dụng dấu ngoặc đơn để xác định rõ ràng thứ tự các phép toán.
- Xem xét khả năng tương thích của trình duyệt: Kiểm tra khả năng tương thích của trình duyệt và sử dụng trình chuyển mã nếu cần thiết để hỗ trợ các trình duyệt cũ hơn.
- Sử dụng một cách nhất quán: Áp dụng
??
ở những nơi thích hợp để có một phong cách viết mã dễ dự đoán hơn trong toàn bộ dự án. - Kết hợp với optional chaining: Sử dụng
??
cùng với optional chaining?.
để truy cập và gán giá trị mặc định một cách an toàn cho các thuộc tính lồng nhau của đối tượng.
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:
- Bản địa hóa: Các giá trị mặc định có thể cần được bản địa hóa dựa trên ngôn ngữ hoặc khu vực của người dùng. Ví dụ, một ký hiệu tiền tệ hoặc định dạng ngày mặc định.
- Chuẩn mực văn hóa: Một số giá trị mặc định có thể cần được điều chỉnh dựa trên chuẩn mực văn hóa. Ví dụ, một thông điệp chào mừng mặc định có thể cần phải khác nhau ở các nền văn hóa khác nhau.
- Khả năng tiếp cận: Đảm bảo rằng các giá trị mặc định có thể tiếp cận và dễ hiểu đối với người dùng khuyết tật. Cung cấp các nhãn rõ ràng và mô tả cho các giá trị mặc định trong giao diện người dùng.
- Múi giờ và ngày tháng: Khi làm việc với ngày và giờ, hãy sử dụng múi giờ và định dạng ngày phù hợp để đảm bảo rằng các giá trị mặc định được hiển thị chính xác cho người dùng ở các khu vực khác nhau.
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.