Property Lookup & Shadowing

Med

When 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