JavaScript Objects and Prototypes
Understand own properties, prototype chains, shared methods, constructor prototypes, classes, descriptors, and deliberate prototype control.
Intermediate
JavaScript objects are not isolated bags of properties. Ordinary objects have a prototype, and property lookup can continue through that prototype chain when the object does not have the property itself. This lesson turns that mechanism into a practical model you can use to read inheritance, build shared behavior, and avoid common prototype mistakes.
Every object has a prototype link
An ordinary object has an internal [[Prototype]] value. You do not normally read that internal slot directly, but the language exposes operations such as Object.getPrototypeOf() and Object.setPrototypeOf() for observing and changing the relationship. The prototype is another object or null; it is not the same thing as the object’s own properties.
Output
Ready to run.
Quick check
Which statement best describes Object.create(base)?
Object.create()
Own properties versus inherited properties
A property can belong directly to the object or be found on one of its prototypes. Object.hasOwn() answers the first question. The in operator answers the broader question: whether the property is available through the object or its prototype chain.
|
|
Output
Ready to run.
Quick check
Which test asks whether a property is directly owned by the object?
const result = ;
Property lookup walks the prototype chain
When ordinary property lookup does not find an own property, the lookup can continue with the object’s prototype, then that prototype’s prototype, until it finds a property or reaches null. This is why methods supplied by built-in prototypes can be called on individual values.
Output
Ready to run.
Quick check
If child has no own kind but its prototype has kind, what does child.kind read?
const parent = { kind: "parent" };
const child = Object.create(parent);
const result = child.kind;
console.log(result);
Writing does not usually update the prototype
Reading and writing are different operations. If an ordinary object has no own property, a read may find an inherited value. A simple assignment such as child.count = 1 normally creates or updates an own data property on child instead of changing the inherited property on the prototype.
Output
Ready to run.
Quick check
After child.count = 1 when count exists only on the prototype, where is the normal assignment stored?
const proto = { count: 0 };
const child = Object.create(proto);
child.count = ;
Methods can be shared through a prototype
A prototype is useful when many objects need the same behavior. Put a method on the shared prototype and let each instance resolve the method through the chain. The method can still use this: the receiver is the object on which the method was called, not the prototype where the function was found.
Output
Ready to run.
Quick check
Why can one prototype method use different object data for different calls?
const methods = { read() { return this.value; } };
const box = Object.create(methods);
box.value = 3;
const result = box.read();
console.log(result);
Constructor functions connect to prototype objects
Traditional constructor functions use a function’s prototype property as part of the object-creation model. With new Person(), JavaScript creates a new object whose prototype is normally Person.prototype, then calls the constructor with the new object as this. This is one reason function objects and prototypes belong in the same mental model.
Output
Ready to run.
Quick check
Where is sayHello stored in this constructor example?
function Person() {}
Person.prototype.sayHello = () => "hi";
const result = Object.hasOwn(Person, "sayHello");
console.log(result);
The prototype property is not the same as [[Prototype]]
This distinction causes many confusing explanations. A function object may have a property named prototype. That property points to an object commonly used as the prototype of instances created by that function. Separately, every ordinary object has its own internal [[Prototype]] link. For an instance, Object.getPrototypeOf(instance) is the link to follow.
Output
Ready to run.
Quick check
Which expression reveals the [[Prototype]] of an object?
const result = Object.getPrototypeOf({});
Object.create gives explicit prototype control
Object.create is useful when you intentionally want a new object linked to a chosen prototype. Passing null creates an object with no prototype at all. That can be useful for dictionary-like data when you want to avoid inherited names such as toString, but you must then provide any behavior you need yourself.
Output
Ready to run.
Quick check
What is special about Object.create(null)?
const result = Object.getPrototypeOf(Object.create(null));
Classes build on this object model
JavaScript classes provide syntax for constructing and inheriting objects, but they do not replace the prototype model taught here. For constructors, class fields, private elements, static members, super, and class initialization order, continue to the dedicated JavaScript Classes lesson.
Prototype chains are about delegation, not copying
A prototype link does not copy properties into the child object. The child delegates failed reads to the prototype chain. This matters when the prototype changes: inherited reads can observe later changes, while an own property shadows the inherited one.
Output
Ready to run.
Quick check
After user.theme is assigned its own value, what happens when the prototype theme changes?
const proto = { x: 1 };
const obj = Object.create(proto);
obj.x = 2
Changing prototypes is powerful but should be deliberate
Object.setPrototypeOf can change an object’s prototype, but routine application code should usually establish the intended prototype when creating the object instead. Dynamic prototype mutation can make object behavior harder to reason about and can interfere with engine optimizations. Use it when you have a clear reason, not as a default inheritance tool.
Output
Ready to run.
Quick check
Which approach is generally clearer when you already know the desired prototype?
const base = { x: 1 };
const result = Object.create(base);
Property descriptors explain what a property actually permits
An object property is more than a name and a value. Data properties have attributes such as writable, enumerable, and configurable. Accessor properties instead use get and set functions. These descriptors matter when you need precise control over mutation, enumeration, or API behavior.
Output
Ready to run.
Quick check
Which descriptor controls whether a data property can be changed by assignment?
const box = {};
Object.defineProperty(box, "x", { value: 1, writable: false
Authoring rules
Prefer ordinary object literals, classes, or constructor functions for normal application models. Use prototypes deliberately when you want shared behavior or need to understand existing object APIs. Remember that a prototype is a delegation link, not a copied set of properties. Use Object.hasOwn when you mean own-property membership, and in when inherited properties should count. Avoid treating the function’s prototype property as if it were the object’s internal [[Prototype]] link. Avoid changing prototypes dynamically unless the design genuinely requires it.
Practice
Trace a three-level prototype chain by hand. Then build two instances that share one prototype method and verify that the method is one function while this changes with the receiver. Finally, create a null-prototype dictionary and compare Object.hasOwn with in.
Specification references
The governing ECMAScript model is described by the current ECMA-262 sections on ordinary objects, internal methods, property descriptors, and object operations. The specification defines OrdinaryObjectCreate in terms of an object’s [[Prototype]] internal slot and defines ordinary property lookup as continuing to the prototype when an own property is absent. urlECMA-262 — current language specificationhttps://tc39.es/ecma262/
Next step
Next, continue into the object model with property descriptors, getters and setters, object integrity, and metaprogramming through Proxy and Reflect.
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.