Tiếng Việt

Nắm vững toán tử optional chaining (?.) của JavaScript để code sạch hơn, an toàn hơn và mạnh mẽ hơn. Học cách ngăn ngừa lỗi và xử lý các thuộc tính đối tượng lồng sâu một cách dễ dàng.

Toán tử Optional Chaining trong JavaScript: Truy cập Thuộc tính An toàn và Thanh lịch

Việc điều hướng trong một mạng lưới phức tạp của các thuộc tính đối tượng lồng sâu trong JavaScript thường có cảm giác như đi qua một bãi mìn. Chỉ một thuộc tính bị thiếu có thể gây ra lỗi đáng sợ "Cannot read property 'x' of undefined", khiến ứng dụng của bạn dừng đột ngột. Các phương pháp truyền thống để kiểm tra phòng ngừa các giá trị null hoặc undefined trước khi truy cập từng thuộc tính có thể dẫn đến code dài dòng và rườm rà. May mắn thay, JavaScript cung cấp một giải pháp thanh lịch và ngắn gọn hơn: optional chaining.

Optional Chaining là gì?

Optional chaining, được biểu thị bằng toán tử ?., cung cấp một cách để truy cập các thuộc tính đối tượng có thể là null hoặc undefined mà không gây ra lỗi. Thay vì ném ra lỗi khi gặp giá trị nullish (null hoặc undefined) trong chuỗi, nó chỉ đơn giản trả về undefined. Điều này cho phép bạn truy cập an toàn các thuộc tính lồng sâu và xử lý các giá trị có thể bị thiếu một cách duyên dáng.

Hãy nghĩ về nó như một công cụ điều hướng an toàn cho các cấu trúc đối tượng của bạn. Nó cho phép bạn "nối chuỗi" qua các thuộc tính, và nếu tại bất kỳ điểm nào một thuộc tính bị thiếu (null hoặc undefined), chuỗi sẽ ngắt mạch và trả về undefined mà không gây ra lỗi.

Nó hoạt động như thế nào?

Toán tử ?. được đặt sau tên một thuộc tính. Nếu giá trị của thuộc tính ở bên trái toán tử là null hoặc undefined, biểu thức sẽ ngay lập tức đánh giá là undefined. Nếu không, việc truy cập thuộc tính sẽ tiếp tục như bình thường.

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

const user = {
  profile: {
    address: {
      city: "London"
    }
  }
};

// Nếu không có optional chaining, dòng này có thể gây lỗi nếu user.profile hoặc user.profile.address là undefined
const city = user.profile.address.city; // London

// Với optional chaining, chúng ta có thể truy cập an toàn vào city ngay cả khi profile hoặc address bị thiếu
const citySafe = user?.profile?.address?.city; // London

const userWithoutAddress = {
  profile: {},
};

const citySafeUndefined = userWithoutAddress?.profile?.address?.city; // undefined (không có lỗi)

Trong ví dụ đầu tiên, cả có và không có optional chaining, chúng ta đều nhận được "London" vì tất cả các thuộc tính đều tồn tại.

Trong ví dụ thứ hai, userWithoutAddress.profile tồn tại nhưng userWithoutAddress.profile.address thì không. Nếu không có optional chaining, việc truy cập userWithoutAddress.profile.address.city sẽ gây ra lỗi. Với optional chaining, chúng ta nhận được undefined mà không có lỗi.

Lợi ích của việc sử dụng Optional Chaining

Ví dụ và Trường hợp sử dụng Thực tế

1. Truy cập Dữ liệu API

Khi tìm nạp dữ liệu từ một API, bạn thường không có toàn quyền kiểm soát cấu trúc dữ liệu. Một số trường có thể bị thiếu hoặc có giá trị null. Optional chaining là vô giá trong việc xử lý các kịch bản này một cách duyên dáng.

async function fetchData(userId) {
  const response = await fetch(`https://api.example.com/users/${userId}`);
  const data = await response.json();

  // Truy cập email của người dùng một cách an toàn, ngay cả khi thuộc tính 'email' bị thiếu
  const email = data?.profile?.email;
  console.log("Email:", email || "Email không có sẵn"); // Sử dụng nullish coalescing để cung cấp giá trị mặc định

  // Truy cập an toàn vào thành phố trong địa chỉ của người dùng
  const city = data?.address?.city;
  console.log("City: ", city || "Thành phố không có sẵn");


}

fetchData(123); // Ví dụ sử dụng

2. Làm việc với Tùy chọn của Người dùng

Các tùy chọn của người dùng thường được lưu trữ trong các đối tượng lồng nhau. Optional chaining có thể đơn giản hóa việc truy cập các tùy chọn này, ngay cả khi một số tùy chọn không được xác định.

const userPreferences = {
  theme: {
    color: "dark",
  },
};

// Truy cập an toàn cỡ chữ của người dùng, cung cấp giá trị mặc định nếu nó chưa được đặt
const fontSize = userPreferences?.font?.size || 16;
console.log("Font Size:", fontSize); // Output: 16 (giá trị mặc định)

const color = userPreferences?.theme?.color || "light";
console.log("Color Theme:", color); // Output: dark

3. Xử lý Trình lắng nghe Sự kiện (Event Listeners)

Khi làm việc với các trình lắng nghe sự kiện, bạn có thể cần truy cập các thuộc tính của đối tượng sự kiện. Optional chaining có thể giúp ngăn ngừa lỗi nếu đối tượng sự kiện hoặc các thuộc tính của nó không được xác định.

document.getElementById('myButton').addEventListener('click', function(event) {
  // Truy cập an toàn ID của phần tử đích
  const targetId = event?.target?.id;
  console.log("Target ID:", targetId);
});

4. Quốc tế hóa (i18n)

Trong các ứng dụng đa ngôn ngữ, bạn thường cần truy cập các chuỗi đã dịch từ một đối tượng lồng nhau dựa trên ngôn ngữ của người dùng. Optional chaining đơn giản hóa quá trình này.

const translations = {
  en: {
    greeting: "Hello",
    farewell: "Goodbye"
  },
  fr: {
    greeting: "Bonjour",
    //farewell: "Au Revoir" - đã xóa để minh họa
  }
};

const locale = "fr";

// Truy cập an toàn lời chào đã dịch
const greeting = translations?.[locale]?.greeting || "Hello";
console.log("Greeting:", greeting); // Output: Bonjour

// Truy cập an toàn lời tạm biệt đã dịch
const farewell = translations?.[locale]?.farewell || "Goodbye";
console.log("Farewell:", farewell); //Output: Goodbye (mặc định là tiếng Anh)

Optional Chaining với Lời gọi Hàm

Optional chaining cũng có thể được sử dụng để gọi an toàn các hàm có thể không tồn tại. Sử dụng cú pháp ?.() cho việc này.

const myObject = {
  myMethod: function() {
    console.log("Phương thức đã được gọi!");
  }
};

// Gọi phương thức một cách an toàn nếu nó tồn tại
myObject?.myMethod?.(); // Output: Phương thức đã được gọi!

const myObject2 = {};

// Gọi phương thức một cách an toàn, nhưng nó không tồn tại
myObject2?.myMethod?.(); // Không có lỗi, không có gì xảy ra

Optional Chaining với Truy cập Mảng

Optional chaining cũng có thể được sử dụng với việc truy cập mảng, bằng cách sử dụng cú pháp ?.[index]. Điều này hữu ích khi làm việc với các mảng có thể rỗng hoặc không được điền đầy đủ.

const myArray = ["apple", "banana", "cherry"];

// Truy cập an toàn một phần tử mảng
const firstElement = myArray?.[0]; // "apple"

const myArray2 = [];

// Truy cập an toàn một phần tử mảng, sẽ là undefined.
const firstElement2 = myArray2?.[0]; // undefined

const secondElement = myArray?.[10]; // undefined (không có lỗi)

Kết hợp Optional Chaining với Nullish Coalescing

Optional chaining thường hoạt động song song với toán tử nullish coalescing (??). Toán tử nullish coalescing cung cấp một giá trị mặc định khi vế trái của toán tử là null hoặc undefined. Điều này cho phép bạn cung cấp các giá trị dự phòng khi một thuộc tính bị thiếu.

const user = {};

// Truy cập an toàn tên người dùng, cung cấp giá trị mặc định nếu nó chưa được đặt
const name = user?.profile?.name ?? "Người dùng không xác định";
console.log("Name:", name); // Output: Người dùng không xác định

Trong ví dụ này, nếu user.profile hoặc user.profile.name là null hoặc undefined, biến name sẽ được gán giá trị "Người dùng không xác định".

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

Optional chaining là một tính năng tương đối mới của JavaScript (được giới thiệu trong ECMAScript 2020). Nó được hỗ trợ bởi tất cả các trình duyệt hiện đại. Nếu bạn cần hỗ trợ các trình duyệt cũ hơn, bạn có thể cần sử dụng một trình biên dịch như Babel để chuyển đổi code của mình sang phiên bản JavaScript tương thích.

Hạn chế

Các Thực hành Tốt nhất

Kết luận

Toán tử optional chaining của JavaScript là một công cụ mạnh mẽ để viết code sạch hơn, an toàn hơn và mạnh mẽ hơn. Bằng cách cung cấp một cách ngắn gọn để truy cập các thuộc tính có thể bị thiếu, nó giúp ngăn ngừa lỗi, giảm code lặp lại và cải thiện khả năng đọc code. Bằng cách hiểu cách nó hoạt động và tuân theo các thực hành tốt nhất, bạn có thể tận dụng optional chaining để xây dựng các ứng dụng JavaScript linh hoạt và dễ bảo trì hơn.

Hãy áp dụng optional chaining vào các dự án của bạn và trải nghiệm những lợi ích của việc truy cập thuộc tính một cách an toàn và thanh lịch. Nó sẽ làm cho code của bạn dễ đọc hơn, ít bị lỗi hơn và cuối cùng, dễ bảo trì hơn. Chúc bạn viết code vui vẻ!