Bài 9 — Làm việc với Object trong JavaScript
Object (đối tượng) biểu diễn một thực thể có nhiều thuộc tính liên quan — ví dụ một người dùng gồm tên, email, mật khẩu. Trong khi array là danh sách theo thứ tự, object là tập hợp các cặp tên–giá trị. Object có mặt khắp nơi trong automation: dữ liệu test, file cấu hình Playwright, response API đều là object.
Cú pháp object
const nguoiDung = {
ten: 'Nguyễn Văn A',
email: 'a@test.com',
tuoi: 25,
daKichHoat: true,
};
console.log(nguoiDung.ten); // 'Nguyễn Văn A'
console.log(nguoiDung.email); // 'a@test.com'
- Object đặt trong
{ }. - Mỗi mục là một cặp
key: value(khóa: giá trị), ngăn bởi dấu phẩy. keylà tên thuộc tính (property);valuelà giá trị, có thể thuộc bất kỳ kiểu nào.
Truy cập thuộc tính: hai cách
console.log(nguoiDung.email); // cách dấu chấm (phổ biến nhất)
console.log(nguoiDung['email']); // cách ngoặc vuông
- Dấu chấm (
.email) — ngắn gọn, dùng khi biết trước tên thuộc tính. - Ngoặc vuông (
['email']) — dùng khi tên thuộc tính nằm trong một biến, hoặc chứa ký tự đặc biệt.
Thêm, sửa, xóa thuộc tính
const nguoiDung = { ten: 'An', tuoi: 20 };
nguoiDung.email = 'an@test.com'; // thêm thuộc tính mới
nguoiDung.tuoi = 21; // sửa thuộc tính có sẵn
delete nguoiDung.email; // xóa thuộc tính
console.log(nguoiDung); // { ten: 'An', tuoi: 21 }
Lưu ý: một object khai báo bằng const vẫn có thể thay đổi thuộc tính bên trong. const chỉ ngăn gán lại toàn bộ biến, không “đóng băng” nội dung object.
Object lồng nhau và mảng object
Giá trị của một thuộc tính có thể lại là object hoặc array — cho phép biểu diễn dữ liệu phức tạp:
const cauHinh = {
baseURL: 'https://demo.com',
trinhDuyet: {
ten: 'chromium',
headless: true,
},
retries: 2,
};
console.log(cauHinh.trinhDuyet.ten); // 'chromium' — truy cập nhiều cấp
Cấu trúc lồng nhau này chính là hình dạng của file playwright.config bạn sẽ gặp ở Bài 16.
Optional chaining ?. — truy cập an toàn nhiều cấp. Khi truy cập một thuộc tính có thể không tồn tại, chạm tới cấp sâu hơn sẽ gây lỗi:
const nguoiDung = { ten: 'An' }; // không có thuộc tính diaChi
console.log(nguoiDung.diaChi.thanhPho); // ❌ TypeError: Cannot read properties of undefined
Toán tử optional chaining ?. giải quyết: nếu phần bên trái là undefined/null, cả biểu thức trả về undefined thay vì ném lỗi:
console.log(nguoiDung.diaChi?.thanhPho); // undefined — không lỗi
Đây là cách xử lý dữ liệu “có thể thiếu” rất phổ biến, đặc biệt khi làm việc với response API (Bài 29) — nơi một trường có thể vắng mặt.
Kết hợp array và object (rất phổ biến — một danh sách bản ghi):
const danhSachNguoiDung = [
{ ten: 'An', vaiTro: 'admin' },
{ ten: 'Bình', vaiTro: 'user' },
];
// Duyệt bằng for...of (Bài 6)
for (const u of danhSachNguoiDung) {
console.log(`${u.ten} — ${u.vaiTro}`);
}
// Hoặc lọc bằng filter (Bài 8)
const admins = danhSachNguoiDung.filter((u) => u.vaiTro === 'admin');Đây là cách bạn tổ chức dữ liệu test: mỗi bộ dữ liệu là một object, nhiều bộ gộp thành một mảng để chạy lặp.
Duyệt các thuộc tính của object
Array duyệt bằng for...of (Bài 6), nhưng object thì khác. Để đi qua các thuộc tính, dùng for...in (nhắc lại từ Bài 6 — vòng lặp này duyệt khóa, đúng việc cần ở đây):
const nguoiDung = { ten: 'An', tuoi: 25, email: 'an@test.com' };
for (const khoa in nguoiDung) {
console.log(`${khoa}: ${nguoiDung[khoa]}`); // dùng ngoặc vuông vì khóa nằm trong biến
}
// ten: An
// tuoi: 25
// email: an@test.com
Chú ý nguoiDung[khoa] dùng ngoặc vuông — vì khoa là một biến chứa tên thuộc tính (không viết được bằng dấu chấm).
Cách hiện đại hơn, thường được ưu tiên, là biến các thuộc tính thành mảng rồi dùng phương thức mảng (Bài 8):
Object.keys(nguoiDung); // ['ten', 'tuoi', 'email'] — mảng các khóa
Object.values(nguoiDung); // ['An', 25, 'an@test.com'] — mảng các giá trị
Object.entries(nguoiDung); // [['ten','An'], ['tuoi',25], ...] — mảng cặp [khóa, giá trị]
Object.keys đặc biệt hữu ích để đếm số thuộc tính (Object.keys(obj).length) hoặc duyệt bằng for...of/forEach.
Destructuring — lấy nhanh thuộc tính ra biến
Destructuring cho phép trích các thuộc tính của object ra thành biến riêng, gọn hơn nhiều so với gán từng dòng:
const nguoiDung = { ten: 'An', email: 'an@test.com', tuoi: 25 };
// Cách thường
const ten = nguoiDung.ten;
const email = nguoiDung.email;
// Destructuring — tương đương, ngắn hơn
const { ten, email } = nguoiDung;
console.log(ten, email); // An an@test.com
Tên biến trong { } phải trùng tên thuộc tính. Bạn sẽ thấy destructuring xuất hiện dày đặc trong code Playwright, ví dụ test('...', async ({ page }) => { ... }) — chính là lấy thuộc tính page ra khỏi một object. Quen mặt cú pháp này từ bây giờ sẽ giúp bạn đọc code Playwright dễ dàng.
Liên hệ với testing
Ví dụ tư duy — một bộ dữ liệu test đăng nhập:
const taiKhoanTest = {
email: 'test@demo.com',
matKhau: 'Test@1234',
};
const { email, matKhau } = taiKhoanTest;
console.log(`Đăng nhập với ${email}`);
// Về sau: page.getByLabel('Email').fill(email)
Gom dữ liệu test vào object giúp test sạch, dễ thay đổi, và dễ tách ra file riêng (Bài 24).
Lỗi thường gặp
- Truy cập thuộc tính không tồn tại → nhận
undefined(không báo lỗi ngay). Nếu truy cập tiếp một cấp nữa trênundefined→TypeError: Cannot read properties of undefined. Khi dữ liệu có thể thiếu, dùng optional chaining?.(xem trên). - Nhầm object với array: object dùng
{ }và truy cập bằng tên khóa; array dùng[ ]và truy cập bằng chỉ số số. - Tưởng
constkhóa được nội dung object: không —constchỉ chặn gán lại toàn bộ biến, thuộc tính bên trong vẫn sửa được.
Ở Bài 10 ta học phần quan trọng nhất của giai đoạn này: bất đồng bộ, Promise và async/await — nền tảng để hiểu mọi dòng code Playwright.
🛠 Thực hành
- Tạo hồ sơ: tạo object
sanPhamgồmten,gia,conHang(boolean). In từng thuộc tính, rồi sửagiavà thêm thuộc tínhgiamGia. - Duyệt object: với object
sanPhamtrên, dùngfor...inin ra tất cảkhóa: giá trị. Sau đó dùngObject.keysin ra số lượng thuộc tính. - Optional chaining: cho object
{ ten: 'An' }(không códiaChi), innguoiDung.diaChi?.thanhPhovà xác nhận nó trả vềundefinedchứ không ném lỗi. - Mảng object: tạo mảng 3 object sản phẩm, dùng
filterlấy các sản phẩmconHang === true, rồimapđể lấy ra mảng chỉ gồm tên. - Destructuring: từ object
{ hoTen: 'Le Van C', email: 'c@test.com', tuoi: 30 }, dùng destructuring lấyhoTenvàemailra biến rồi in bằng template literal.
Website tham khảo
- MDN — JavaScript object basics (tiếng Việt) — object cho người mới.
- javascript.info — Objects — object chi tiết.
- javascript.info — Destructuring assignment — destructuring đầy đủ.