Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Ghi đè thuộc tính kế thừa (Override Derived Properties) trong JavaScript

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ỏ đến objPerson
  • Đọ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';