Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

JavaScript Objects and Prototypes

Understand own properties, prototype chains, shared methods, constructor prototypes, classes, descriptors, and deliberate prototype control.

Levels: Intermediate ~32 min read

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.

Interactive Runnable example
Edit

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.

javascript ownership.js
1
2
3
4
5
6
7
const base = { category: "book" };
const item = Object.create(base);
item.title = "Guide";

Object.hasOwn(item, "title");    // true
Object.hasOwn(item, "category"); // false
"category" in item;               // true
Interactive Runnable example
Edit

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.

Interactive Runnable example
Edit

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.

Interactive Runnable example
Edit

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.

Interactive Runnable example
Edit

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.

Interactive Runnable example
Edit

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.

Interactive Runnable example
Edit

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.

Interactive Runnable example
Edit

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.

Interactive Runnable example
Edit

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.

Interactive Runnable example
Edit

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.

Interactive Runnable example
Edit

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. urlECMA-262 — current language specificationhttps://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.

Was this page helpful?

Mark this learning resource complete to track your learning progress.