Object là một nhóm giá trị có tên, gói trong một biến. Nhân vật có tên, máu, level, vũ khí. Thay vì bốn biến rời, bạn gom vào một object player và gọi từng phần bằng tên.
Tạo object
Viết trong ngoặc nhọn, mỗi dòng là một cặp tên: giá trị, ngăn bằng dấu phẩy.
const player = {
name: "Aki",
hp: 100,
level: 3,
isAlive: true,
};
console.log(player); // { name: 'Aki', hp: 100, level: 3, isAlive: true }
Mỗi cặp gọi là một thuộc tính (property). name là tên thuộc tính (key), "Aki" là giá trị.
Vì sao gom lại: khi có hai nhân vật, bạn không phải đặt player1Hp, player2Hp. Mỗi object tự giữ dữ liệu của nó.
Đọc thuộc tính bằng dấu chấm
console.log(player.name); // Aki
console.log(player.hp); // 100
Sửa cũng bằng dấu chấm:
player.hp = player.hp - 20;
player.level += 1;
console.log(player.hp, player.level); // 80 4
player khai báo bằng const vẫn sửa bên trong được. const chỉ chặn gán một object khác vào biến.
Đọc bằng ngoặc vuông
Dấu chấm cần bạn biết tên thuộc tính lúc viết code. Nhưng có lúc tên nằm trong một biến, ví dụ người chơi chọn chỉ số muốn nâng.
const stats = { str: 5, agi: 3, int: 7 };
const chosen = "agi";
console.log(stats.chosen); // undefined
console.log(stats[chosen]); // 3
stats.chosen tìm một thuộc tính tên là chosen, không có nên ra undefined. stats[chosen] lấy giá trị của biến chosen (là "agi") rồi mới tìm. Muốn dùng tên nằm trong biến thì phải dùng ngoặc vuông.
stats[chosen] += 1;
console.log(stats); // { str: 5, agi: 4, int: 7 }
Ngoặc vuông cũng dùng khi tên có dấu cách hoặc ký tự đặc biệt: item["fire-resist"].
Lỗi hay gặp: đọc thuộc tính của một thuộc tính chưa có.
player.weapon.damagekhi chưa cóweaponbáoTypeError: Cannot read properties of undefined (reading 'damage'). Dùngplayer.weapon?.damage: nếuweaponkhông có thì trả vềundefinedthay vì lỗi.
Thêm, xoá và kiểm tra thuộc tính
Gán vào một tên chưa có là thêm thuộc tính mới:
const player = { name: "Aki", hp: 100 };
player.weapon = "Kiếm gỗ";
console.log(player); // { name: 'Aki', hp: 100, weapon: 'Kiếm gỗ' }
Xoá bằng delete, kiểm tra bằng in:
delete player.weapon;
console.log("weapon" in player); // false
console.log("hp" in player); // true
Object lồng nhau
Giá trị của thuộc tính có thể là mảng hoặc object khác. Đây là cách dữ liệu game thật thường trông.
const hero = {
name: "Aki",
stats: { hp: 100, attack: 12 },
inventory: ["bình máu", "chìa khóa"],
};
console.log(hero.stats.attack); // 12
console.log(hero.inventory[0]); // bình máu
console.log(hero.inventory.length); // 2
Hàm trong object
Thuộc tính có thể là một hàm. Hàm đó gọi là method, dùng this để trỏ tới chính object.
const enemy = {
name: "Goblin",
hp: 30,
takeDamage(amount) {
this.hp = Math.max(0, this.hp - amount);
console.log(`${this.name} còn ${this.hp} máu`);
},
};
enemy.takeDamage(12); // Goblin còn 18 máu
enemy.takeDamage(50); // Goblin còn 0 máu
Math.max(0, ...) giữ máu không xuống số âm.
Lấy danh sách key
Object.keys trả về mảng tên thuộc tính, tiện để in bảng chỉ số:
const stats = { str: 5, agi: 3, int: 7 };
console.log(Object.keys(stats)); // [ 'str', 'agi', 'int' ]
Để lặp qua từng cặp, xem for...of ở trang Vòng lặp. Muốn lưu object ra file hay localStorage, xem trang JSON.
Bài tập
Tạo object monster có name là "Slime", hp là 40, drops là mảng ["gel", "vàng"]. Trừ 15 máu, thêm thuộc tính isBoss là false, rồi in Slime còn 25 máu, rơi 2 món.
Xem đáp án
const monster = {
name: "Slime",
hp: 40,
drops: ["gel", "vàng"],
};
monster.hp -= 15;
monster.isBoss = false;
console.log(`${monster.name} còn ${monster.hp} máu, rơi ${monster.drops.length} món`);
// Slime còn 25 máu, rơi 2 món