Khái niệm
Khi một đối tượng được tạo từ prototype (qua Object.create()), nó kế thừa các thuộc tính. Việc gán giá trị mới cho thuộc tính đó trên instance sẽ tạo shadow property (che khuất) thay vì sửa đổi prototype gốc.
Ví dụ minh họa
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Override Derived Properties</title>
<style>
body { font-family: 'Segoe UI', sans-serif; padding: 20px; }
.sample, .result { font-size: 16px; font-weight: 500; margin: 10px 0; padding: 15px; border-radius: 4px; }
.sample { color: #6a1b9a; background: #f3e5f5; }
.result { color: #d32f2f; background: #ffebee; }
button { padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }
</style>
</head>
<body>
<h1>Ghi đè thuộc tính kế thừa</h1>
<div class="sample" id="sample">Trước khi ghi đè:<br></div>
<div class="result" id="result">Sau khi ghi đè:<br></div>
<button id="btn">GHI ĐÈ THUỘC TÍNH</button>
<h3>Nhấn nút để ghi đè thuộc tính của Person1</h3>
<script>
const sampleEle = document.getElementById('sample');
const resEle = document.getElementById('result');
const btnEle = document.getElementById('btn');
// Prototype object
const objPerson = { name: 'Rahul', age: 12, class: 7 };
// Tạo object kế thừa từ objPerson
const Person1 = Object.create(objPerson);
// Hiển thị giá trị kế thừa (chưa ghi đè)
sampleEle.innerHTML += `Person1.name = ${Person1.name} (kế thừa)<br>`;
sampleEle.innerHTML += `Person1.age = ${Person1.age} (kế thừa)<br>`;
sampleEle.innerHTML += `Person1.class = ${Person1.class} (kế thừa)<br>`;
btnEle.addEventListener('click', () => {
// Ghi đè (tạo own property)
Person1.name = 'Shawn';
Person1.age = 18;
Person1.class = 12;
resEle.innerHTML += `Person1.name = ${Person1.name} (own property)<br>`;
resEle.innerHTML += `Person1.age = ${Person1.age} (own property)<br>`;
resEle.innerHTML += `Person1.class = ${Person1.class} (own property)<br>`;
// Kiểm tra
resEle.innerHTML += `\n--- Kiểm tra ---\n`;
resEle.innerHTML += `Person1.hasOwnProperty('name'): ${Person1.hasOwnProperty('name')}\n`;
resEle.innerHTML += `objPerson.name (gốc): ${objPerson.name}\n`;
});
</script>
</body>
</html>
Kết quả
Trước khi ghi đè:
Person1.name = Rahul (kế thừa) Person1.age = 12 (kế thừa) Person1.class = 7 (kế thừa)
Sau khi ghi đè:
Person1.name = Shawn (own property)
Person1.age = 18 (own property)
Person1.class = 12 (own property)
Person1.hasOwnProperty('name'): true
objPerson.name (gốc): Rahul
Giải thích
Object.create(objPerson)tạo object mới với__proto__trỏ đếnobjPerson- Đọc thuộc tính: JS tìm trên object → không thấy → tìm lên prototype chain
- Ghi thuộc tính: JS **luôn tạo** own property trên object hiện tại (shadowing)
- Prototype gốc không bị thay đổi
So sánh: Ghi đè vs Sửa đổi Prototype
// Ghi đè (Shadowing) - CHỈ ẢNH HƯỞNG INSTANCE NÀY
Person1.name = 'Shawn';
// Sửa đổi prototype - ẢNH HƯỞNG TẤT CẢ INSTANCE
Person.prototype.name = 'New Default';