Property Lookup & Shadowing
MedWhen you access a property, JavaScript walks up the prototype chain until it finds the property or reaches null. Setting a property always creates or updates an own property on the object itself. When an object has a property with the same name as one on its prototype, the own property "shadows" (hides) the inherited one.
Interactive Visualization
Look up:
Property Lookup
dog
name:"Rex"
age:3
__proto__: → Animal.prototype
↓ __proto__
Animal.prototype
speak:fn()
eat:fn()
__proto__: → Object.prototype
↓ __proto__
Object.prototype
toString:fn()
hasOwnProperty:fn()
__proto__: → null
↓ __proto__
null
End of chain
Select a property above to see the lookup animation
Key Insight: Own properties are found immediately without walking the prototype chain.
Key Points
- Get: Walk up prototype chain until found or null
- Set: Always creates/updates own property (never modifies prototype)
- Own property shadows inherited property with same name
- hasOwnProperty() checks only own properties
- in operator checks entire chain including prototypes
Code Examples
Property Lookup Walk
const proto = { x: 1, y: 2 }; const obj = Object.create(proto); obj.x = 10; // Own property console.log(obj.x); // 10 (own property) console.log(obj.y); // 2 (from prototype) console.log(obj.z); // undefined (not found) // Lookup process for obj.y: // 1. Check obj own properties - not found // 2. Check obj.__proto__ (proto) - found y: 2 // 3. Return 2 // Lookup process for obj.z: // 1. Check obj - not found // 2. Check proto - not found // 3. Check Object.prototype - not found // 4. Check null - end of chain // 5. Return undefined
Getting walks up the chain. Setting creates own property.
Shadowing
const parent = { name: "Parent", value: 100 }; const child = Object.create(parent); child.name = "Child"; // Shadows parent.name console.log(child.name); // "Child" (own property) console.log(parent.name); // "Parent" (unchanged!) // Setting never modifies the prototype // It always creates an own property // child.value = child.value + 1; // This reads parent.value (100), adds 1, sets child.value to 101 // parent.value is still 100
When an object has a property with the same name as its prototype, the own property shadows the inherited one.
hasOwnProperty vs in
const parent = { inherited: true }; const child = Object.create(parent); child.own = true; // hasOwnProperty: only own properties console.log(child.hasOwnProperty('own')); // true console.log(child.hasOwnProperty('inherited')); // false // in operator: checks entire chain console.log('own' in child); // true console.log('inherited' in child); // true console.log('toString' in child); // true (from Object.prototype) // Iteration safety for (let key in child) { if (child.hasOwnProperty(key)) { console.log(key); // Only "own" } }
hasOwnProperty checks only own properties. in operator checks entire prototype chain.
Common Mistakes
- Thinking setting a property updates the prototype
- Using for...in without hasOwnProperty check
- Not understanding that hasOwnProperty is different from in operator
Interview Tips
- Know the difference between hasOwnProperty and in
- Understand that setting always creates own property
- Know shadowing behavior
- Explain the lookup walk process