Object, destructuring và spread trong JavaScript hiện đại

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Đối tượng (object) là cấu trúc dữ liệu bạn dùng nhiều nhất trong JavaScript: thông tin người dùng, cấu hình, phản hồi từ API. Các cú pháp hiện đại như destructuring, spread và optional chaining giúp làm việc với object gọn và an toàn hơn rất nhiều. Hãy cùng xem từng thứ.

Object cơ bản

const user = {
  ten: 'Lan',
  tuoi: 22,
  diaChi: { thanhPho: 'Đà Nẵng' },
  sach: ['JS', 'CSS'],
};

console.log(user.ten);           // chấm
console.log(user['tuoi']);       // ngoặc vuông
user.email = 'lan@example.com'; // thêm thuộc tính
delete user.tuoi;               // xóa thuộc tính

Ngoặc vuông hữu ích khi tên thuộc tính nằm trong biến, ví dụ user[tenTruong]. Rút gọn khi tên biến trùng tên thuộc tính: const ten = 'Nam'; const u = { ten }; tương đương { ten: ten }. Hàm trong object (phương thức) cũng viết gọn được: { chao() { return 'Xin chào'; } }.

Destructuring: bóc tách giá trị

Thay vì viết nhiều dòng lấy từng thuộc tính, bạn bóc chúng ra trong một lần:

const { ten, tuoi } = user;

// đổi tên biến và đặt giá trị mặc định
const { ten: hoTen, quocGia = 'Việt Nam' } = user;

// object lồng nhau
const { diaChi: { thanhPho } } = user;

Với mảng, destructuring dựa vào vị trí:

const [dau, thuHai, ...conLai] = [10, 20, 30, 40];
// dau = 10, thuHai = 20, conLai = [30, 40]

// hoán đổi hai biến
let a = 1, b = 2;
[a, b] = [b, a];

Destructuring cực kỳ hữu ích ở tham số hàm, vì bạn thấy ngay hàm cần những trường nào:

function hienThi({ ten, tuoi = 18 }) {
  return ten + ' - ' + tuoi;
}
hienThi({ ten: 'Mai' }); // 'Mai - 18'

Spread: trải phẳng và sao chép

Toán tử ba chấm khi dùng ở phía phải sẽ trải các phần tử ra:

const a = [1, 2];
const b = [...a, 3, 4];       // [1, 2, 3, 4]

const goc = { ten: 'Lan', tuoi: 22 };
const moi = { ...goc, tuoi: 23 }; // { ten: 'Lan', tuoi: 23 }

Đây là cách thông dụng để tạo bản sao có chỉnh sửa mà không động vào bản gốc, rất quan trọng trong React và các thư viện quản lý trạng thái. Thuộc tính viết sau sẽ ghi đè thuộc tính viết trước.

Cẩn thận: spread chỉ sao chép nông (shallow). Với object lồng nhau, đối tượng bên trong vẫn là cùng một tham chiếu:

const banSao = { ...user };
banSao.diaChi.thanhPho = 'Huế';
console.log(user.diaChi.thanhPho); // 'Huế', user cũng bị đổi!

Muốn sao chép sâu, bạn có thể dùng structuredClone(user) có sẵn trong các môi trường hiện đại, hoặc tạo bản sao riêng cho từng cấp lồng khi cập nhật.

Rest: gom phần còn lại

Cũng là ba chấm nhưng ở phía bên trái dấu bằng hoặc ở tham số, nó gom phần còn lại:

const { ten, ...phanConLai } = user;
// phanConLai chứa mọi thuộc tính trừ ten

Mẹo này tiện để loại bỏ một thuộc tính khỏi bản sao mà không sửa bản gốc.

Optional chaining và nullish coalescing

Khi dữ liệu có thể thiếu, truy cập sâu dễ gây lỗi "Cannot read properties of undefined". Optional chaining ?. dừng lại và trả về undefined thay vì ném lỗi:

const thanhPho = user.diaChi?.thanhPho;
const soNha = user.diaChi?.soNha ?? 'Chưa cập nhật';
const dau = user.sach?.[0];
const kq = user.chao?.();   // chỉ gọi nếu chao là hàm

Toán tử ?? chỉ dùng giá trị phía sau khi vế trái là null hoặc undefined. Khác với ||, nó giữ lại các giá trị như 0 và chuỗi rỗng, thứ thường là dữ liệu hợp lệ.

Duyệt qua object

Object.keys(user);     // mảng tên thuộc tính
Object.values(user);   // mảng giá trị
Object.entries(user);  // mảng cặp [khóa, giá trị]

for (const [khoa, giaTri] of Object.entries(user)) {
  console.log(khoa, giaTri);
}

Ví dụ: cập nhật trạng thái không làm đổi dữ liệu gốc

Trong React hay Redux, bạn không được sửa trực tiếp trạng thái, mà phải tạo bản mới. Spread là công cụ chính cho việc đó:

const gioHang = [{ id: 1, sl: 1 }, { id: 2, sl: 3 }];

// tăng số lượng của sản phẩm id = 2
const moi = gioHang.map(sp =>
  sp.id === 2 ? { ...sp, sl: sp.sl + 1 } : sp
);

// thêm sản phẩm
const them = [...gioHang, { id: 3, sl: 1 }];

Mảng gốc gioHang không đổi. Thói quen bất biến (immutability) này làm cho việc theo dõi thay đổi và gỡ lỗi dễ dàng hơn rất nhiều.

Kết luận

Destructuring giúp đọc và khai báo dữ liệu gọn, spread giúp tạo bản sao có chỉnh sửa, rest gom phần còn lại, còn ?. với ?? giúp xử lý dữ liệu thiếu an toàn. Hãy thực hành bằng cách viết lại những đoạn mã dài dòng cũ của bạn theo các cú pháp này.

Để áp dụng các kiến thức này vào dự án thật như ứng dụng quản lý công việc, bạn có thể xem các khóa học tại codebem.com.

author_photo
Nguyễn Đình Cường

0 comment