Cách sử dụng Destructuring trong JavaScript

Javascript căn bản | by Học Javascript

Trong JavaScript, Destructuring là một tính năng mạnh mẽ giúp trích xuất dữ liệu từ ArrayObject một cách nhanh chóng và gọn gàng. Thay vì truy xuất từng phần tử hoặc thuộc tính theo cách thông thường, Destructuring cho phép lập trình viên viết mã ngắn gọn hơn, dễ hiểu hơn và tránh lặp lại không cần thiết.

Destructuring đóng vai trò quan trọng trong việc xử lý dữ liệu, đặc biệt khi làm việc với API, React, Vue, hoặc trong các tình huống cần trích xuất dữ liệu nhanh chóng. Có hai loại destructuring phổ biến:

  • Array Destructuring – giúp trích xuất phần tử từ mảng.
  • Object Destructuring – giúp trích xuất thuộc tính từ đối tượng.

Bài viết này sẽ hướng dẫn chi tiết về cách sử dụng Destructuring trong JavaScript, từ cú pháp cơ bản đến những ứng dụng thực tế giúp tối ưu hóa code.

Destructuring trong JavaScript là gì?

Destructuring là một cú pháp trong JavaScript cho phép trích xuất giá trị từ Array hoặc Object và gán chúng vào các biến một cách nhanh chóng. Thay vì truy xuất từng phần tử hoặc thuộc tính bằng cách sử dụng chỉ mục hoặc dấu chấm (.), Destructuring giúp viết code ngắn gọn và dễ đọc hơn.

Destructuring với Array

Thay vì truy xuất từng phần tử bằng cách sử dụng chỉ mục:

const numbers = [1, 2, 3];
const first = numbers[0];
const second = numbers[1];
console.log(first, second); // 1 2

Bạn có thể sử dụng Destructuring để viết ngắn gọn hơn:

const numbers = [1, 2, 3];
const [first, second] = numbers;
console.log(first, second); // 1 2

Destructuring với Object

Thông thường, truy xuất thuộc tính của Object:

const person = { name: "John", age: 30 };
const name = person.name;
const age = person.age;
console.log(name, age); // John 30

Với Destructuring, có thể viết ngắn gọn hơn:

const person = { name: "John", age: 30 };
const { name, age } = person;
console.log(name, age); // John 30

Destructuring với Array

Cú pháp cơ bản

Destructuring với Array giúp trích xuất từng phần tử từ một mảng và gán chúng vào các biến một cách ngắn gọn.

const numbers = [10, 20, 30];
const [a, b, c] = numbers;
console.log(a, b, c); // 10 20 30

Ở đây, a sẽ lấy phần tử đầu tiên, b lấy phần tử thứ hai, và c lấy phần tử thứ ba trong mảng numbers.

Gán giá trị mặc định

Nếu một phần tử không tồn tại trong mảng, có thể gán giá trị mặc định để tránh lỗi undefined.

const values = [42];
const [x, y = 100] = values;
console.log(x, y); // 42 100

Trong trường hợp này:

  • x nhận giá trị 42 (phần tử đầu tiên của mảng).
  • y không có giá trị tương ứng trong mảng nên nhận giá trị mặc định 100.

Bỏ qua phần tử khi destructuring

Có thể bỏ qua một hoặc nhiều phần tử trong mảng bằng cách sử dụng dấu phẩy , để nhảy qua vị trí không cần thiết.

const colors = ["red", "green", "blue", "yellow"];
const [, secondColor, , fourthColor] = colors;
console.log(secondColor, fourthColor); // green yellow

Ở đây:

  • Dấu , đầu tiên bỏ qua phần tử đầu tiên "red".
  • secondColor nhận "green".
  • Dấu , thứ hai bỏ qua phần tử "blue".
  • fourthColor nhận "yellow".

Trích xuất phần còn lại với Rest Operator (...)

Có thể dùng Rest Operator (...) để lấy các phần tử còn lại của mảng sau khi đã trích xuất một số phần tử.

const fruits = ["apple", "banana", "cherry", "mango", "orange"];
const [first, second, ...rest] = fruits;
console.log(first); // apple
console.log(second); // banana
console.log(rest); // ["cherry", "mango", "orange"]

Ở đây:

  • first lấy "apple", second lấy "banana".
  • rest chứa tất cả phần tử còn lại: ["cherry", "mango", "orange"].

Hoán đổi giá trị biến bằng Destructuring

Một cách đổi giá trị giữa hai biến mà không cần biến trung gian.

let a = 5, b = 10;
[a, b] = [b, a];
console.log(a, b); // 10 5

Không cần dùng biến tạm, chỉ với một dòng code có thể hoán đổi giá trị của ab.

Destructuring với Object

Cú pháp cơ bản

Object Destructuring giúp trích xuất giá trị từ các thuộc tính của object và gán chúng vào biến.

const person = { name: "Alice", age: 25, city: "Hanoi" };
const { name, age, city } = person;

console.log(name); // Alice
console.log(age); // 25
console.log(city); // Hanoi

Ở đây:

  • name, age, và city sẽ lấy giá trị từ person theo đúng tên thuộc tính.

Đổi tên biến khi destructuring

Có thể đổi tên biến khi destructuring để tránh trùng tên biến hoặc để dễ hiểu hơn.

const user = { username: "john_doe", email: "[email protected]" };
const { username: userName, email: userEmail } = user;

console.log(userName); // john_doe
console.log(userEmail); // [email protected]

Ở đây:

  • username được đổi tên thành userName.
  • email được đổi tên thành userEmail.

Gán giá trị mặc định khi destructuring

Khi một thuộc tính không tồn tại trong object, có thể gán giá trị mặc định để tránh lỗi undefined.

const product = { name: "Laptop", price: 1500 };
const { name, price, stock = 0 } = product;

console.log(name); // Laptop
console.log(price); // 1500
console.log(stock); // 0 (vì product không có thuộc tính stock nên lấy giá trị mặc định)

Ở đây:

  • stock không có trong object product, nên sẽ nhận giá trị mặc định 0.

Trích xuất phần còn lại với Rest Operator (...)

Có thể sử dụng Rest Operator (...) để lấy tất cả các thuộc tính còn lại trong object sau khi destructuring.

const car = { brand: "Toyota", model: "Camry", year: 2023, color: "red" };
const { brand, model, ...rest } = car;

console.log(brand); // Toyota
console.log(model); // Camry
console.log(rest); // { year: 2023, color: "red" }

Ở đây:

  • brandmodel được trích xuất riêng.
  • rest chứa tất cả các thuộc tính còn lại (yearcolor).

Destructuring với Object lồng nhau

Có thể trích xuất dữ liệu từ object có cấu trúc lồng nhau.

const student = {
  name: "Emma",
  info: {
    age: 20,
    major: "Computer Science",
    address: { city: "New York", country: "USA" }
  }
};

const { name, info: { age, major, address: { city, country } } } = student;

console.log(name); // Emma
console.log(age); // 20
console.log(major); // Computer Science
console.log(city); // New York
console.log(country); // USA

Kết quả:

Ở đây:

  • Trích xuất name từ student.
  • Trích xuất age, major từ info.
  • Trích xuất city, country từ address.

Destructuring trong hàm

Destructuring trong hàm giúp trích xuất dữ liệu từ tham số đầu vào một cách nhanh chóng, làm cho code gọn gàng và dễ đọc hơn.

Truyền tham số bằng destructuring

Thay vì truy xuất từng thuộc tính của object hoặc array trong hàm, ta có thể destructure trực tiếp trong phần khai báo tham số.

Ví dụ với Array:

function printCoordinates([x, y]) {
  console.log(`Tọa độ: x = ${x}, y = $2025`);
}

const point = [10, 20];
printCoordinates(point); // Tọa độ: x = 10, y = 20

Ở đây:

  • Hàm printCoordinates nhận một mảng [x, y] và destructuring ngay trong tham số.

Ví dụ với Object:

function greet({ name, age }) {
  console.log(`Xin chào, tôi là ${name}, ${age} tuổi.`);
}

const person = { name: "Alice", age: 25 };
greet(person); // Xin chào, tôi là Alice, 25 tuổi.

Ở đây:

  • Hàm greet nhận một object { name, age } và destructuring trực tiếp trong tham số.

Truyền giá trị mặc định trong hàm

Khi tham số không được truyền vào, ta có thể đặt giá trị mặc định để tránh lỗi undefined.

Ví dụ với Array:

function getColors([primary = "red", secondary = "blue"] = []) {
  console.log(`Màu chính: ${primary}, Màu phụ: ${secondary}`);
}

getColors(["green"]); // Màu chính: green, Màu phụ: blue
getColors();          // Màu chính: red, Màu phụ: blue

Ở đây:

  • Nếu primary không có giá trị, nó mặc định là "red".
  • Nếu secondary không có giá trị, nó mặc định là "blue".
  • Nếu không truyền tham số, mặc định sẽ là [].

Ví dụ với Object:

function createUser({ name = "Guest", age = 18 } = {}) {
  console.log(`User: ${name}, ${age} tuổi`);
}

createUser({ name: "John" }); // User: John, 18 tuổi
createUser();                 // User: Guest, 18 tuổi

Ở đây:

  • Nếu name không có giá trị, nó mặc định là "Guest".
  • Nếu age không có giá trị, nó mặc định là 18.
  • Nếu không truyền object nào, mặc định sẽ là {}.

Destructuring với tham số Object trong hàm

Trong một số trường hợp, object có nhiều thuộc tính nhưng chỉ cần lấy một vài thuộc tính cụ thể, ta có thể kết hợp Rest Operator (...).

Ví dụ:

function displayProduct({ name, price, ...rest }) {
  console.log(`Sản phẩm: ${name}, Giá: ${price}`);
  console.log("Thông tin thêm:", rest);
}

const product = {
  name: "Laptop",
  price: 1200,
  brand: "Dell",
  stock: 10
};

displayProduct(product);
// Sản phẩm: Laptop, Giá: 1200
// Thông tin thêm: { brand: 'Dell', stock: 10 }

Kết quả:

Ở đây:

  • Hàm displayProduct chỉ lấy nameprice, còn lại được gom vào rest.

Ứng dụng thực tế của Destructuring

Destructuring trong JavaScript được sử dụng rộng rãi trong nhiều tình huống thực tế, đặc biệt khi làm việc với API, thư viện front-end như React, Vue, hoặc backend với Node.js. Dưới đây là một số ứng dụng phổ biến của destructuring.

Lấy dữ liệu từ API dễ dàng hơn

Khi nhận dữ liệu từ API dưới dạng JSON object, destructuring giúp trích xuất thông tin nhanh chóng mà không cần truy xuất từng cấp.

Ví dụ:

// Giả sử gọi API và nhận được dữ liệu JSON
const userData = {
  id: 1,
  name: "Alice",
  email: "[email protected]",
  address: {
    city: "New York",
    country: "USA"
  }
};

// Sử dụng destructuring để lấy dữ liệu
const { name, email, address: { city } } = userData;

console.log(name);  // Alice
console.log(email); // [email protected]
console.log(city);  // New York

Lợi ích: Giúp lấy dữ liệu từ API một cách nhanh chóng, không cần truy cập từng cấp độ thủ công.

Viết code ngắn gọn, dễ đọc hơn trong React, Vue, Node.js

Trong React (props destructuring)

function UserProfile({ name, age, email }) {
  return (
    <div>
      <h1>{name}</h1>
      <p>Tuổi: {age}</p>
      <p>Email: {email}</p>
    </div>
  );
}

// Truyền props vào component
<UserProfile name="John" age={30} email="[email protected]" />

Lợi ích: Trích xuất dữ liệu từ props giúp component React dễ đọc hơn.

Trong Vue (destructuring trong setup)

export default {
  props: ["user"],
  setup({ user }) {
    const { name, email } = user;
    return { name, email };
  }
};

Lợi ích: Giúp truy xuất dữ liệu props một cách gọn gàng hơn.

Trong Node.js (làm việc với module)

const { readFile, writeFile } = require("fs");

readFile("test.txt", "utf8", (err, data) => {
  if (err) console.log(err);
  else console.log(data);
});

Lợi ích: Tránh phải viết fs.readFile hay fs.writeFile dài dòng.

Truyền dữ liệu vào hàm một cách linh hoạt

Destructuring giúp truyền tham số một cách linh hoạt, đặc biệt khi một hàm có nhiều tham số.

Ví dụ:

function printUserInfo({ name, age, email = "Không có email" }) {
  console.log(`Tên: ${name}, Tuổi: ${age}, Email: ${email}`);
}

const user = { name: "David", age: 28 };
printUserInfo(user); // Tên: David, Tuổi: 28, Email: Không có email

Lợi ích: Hàm có thể nhận object mà không cần nhớ thứ tự tham số.

Kết bài

Destructuring trong JavaScript là một tính năng mạnh mẽ giúp trích xuất dữ liệu từ ArrayObject một cách nhanh chóng và trực quan. Nhờ destructuring, chúng ta có thể viết mã ngắn gọn hơn, dễ đọc hơn, đồng thời tối ưu hóa cách truy xuất dữ liệu trong lập trình.

Tính năng này đặc biệt hữu ích trong việc xử lý dữ liệu từ API, viết code trong React, Vue, Node.js, và nhiều tình huống thực tế khác. Bên cạnh đó, việc sử dụng destructuring kết hợp với Rest Operator (...), giá trị mặc định, đổi tên biến giúp lập trình viên linh hoạt hơn khi làm việc với dữ liệu.

Với những lợi ích mà destructuring mang lại, đây chắc chắn là một kỹ thuật mà mọi lập trình viên JavaScript nên thành thạo để nâng cao hiệu suất và chất lượng mã nguồn của mình.

Bài viết liên quan