Prototypes & Inheritance
Key Learning Objectives
Understand the ECMAScript [[Prototype]] link and prototype chain traversal.
Master property shadowing and how writing to an instance creates own properties.
Learn why the delete operator only removes own properties and never prototype properties.
Distinguish between Object.prototype.hasOwnProperty() and the 'in' operator.
The Interview Problem
What is logged to the console when the following code executes, and how does property deletion interact with shadowed prototype properties?
1function Device(brand) {2 this.brand = brand;3}45Device.prototype.category = 'electronics';6Device.prototype.battery = 100;78const phone = new Device('Acme');910phone.battery = 85;1112const res1 = phone.battery;13delete phone.battery;14const res2 = phone.battery;15delete phone.category;16const res3 = phone.category;17const res4 = phone.hasOwnProperty('battery');18const res5 = 'battery' in phone;1920console.log(res1, res2, res3, res4, res5);
Predict Console Output
Select the option that matches what standard ECMAScript prints to the console:
85 100 electronics false true
85 undefined undefined false false
85 100 undefined true true
85 85 electronics false true
V8 Engine Execution Trace
Step 1 of 10 (Line 1)Device constructor function is declared. V8 engine initializes Device.prototype as an empty object with a constructor property pointing back to Device.
Deep Technical Breakdown
The Prototype Chain Lookup Algorithm in V8
When accessing a property obj.prop:
- The V8 engine checks the own properties (the object's internal shape / hidden class and property storage).
- If found, that value is returned immediately.
- If not found, V8 checks
obj.[[Prototype]](accessible viaObject.getPrototypeOf(obj)or__proto__). - If found on the prototype, that value is returned.
- If not found, the search continues recursively up the chain until it reaches
Object.prototype.[[Prototype]], which isnull. If still not found,undefinedis returned.
Property Shadowing vs Prototype Mutation
- Assignment creates own properties: Writing
phone.battery = 85does NOT mutateDevice.prototype. It creates a new own property onphonewith the value85. This is known as property shadowing. - Delete unmasks the prototype: Running
delete phone.batteryremoves the own property. Subsequent reads fall through toDevice.prototype.battery(100). - Delete never mutates prototypes: Running
delete phone.categoryattempts to delete an own propertycategoryfromphone. Sincephonedoes not owncategory, the operation is a harmless no-op and returnstrue, leavingDevice.prototype.categorycompletely untouched. - Inspection differences:
phone.hasOwnProperty('battery')returnsfalse(only own properties are considered), whereas'battery' in phonereturnstrue(the entire prototype chain is inspected).
Common Traps & Mistakes
Thinking `delete instance.prop` will delete a property on the prototype. To delete a prototype property, you must explicitly call `delete Constructor.prototype.prop`.
Confusing `__proto__` with `.prototype`. `.prototype` is an own property on constructor functions used as the blueprint for instances; `[[Prototype]]` (or `__proto__`) is the actual link on instances.
Mutating shared objects on prototypes: if `Device.prototype.settings = {}`, all instances share the exact same object reference in heap memory, causing shared mutation bugs.
FAANG Follow-Up Probes
Probe #1
How does `Object.create(proto)` differ from `new Constructor()` in setting up prototype delegation?
Probe #2
What is Prototype Pollution, how does it occur with recursive object merges, and how do you protect against it using `Object.create(null)` or `Map`?
Probe #3
How does modern ES6 `class extends` desugar into prototype inheritance, `super()`, and `Object.setPrototypeOf()` under the hood?
