ThisCalculator

Everyday

JavaScript Objects: 5 Key Ideas About Properties and Prototypes

Updated · Standard formula, shown below

JavaScript Objects: 5 Key Ideas About Properties and Prototypes

JavaScript objects store related data and behavior, but their properties can be inherited, hidden from enumeration, or controlled with descriptors. These five ideas explain how properties and prototypes work, and are useful for beginners learning the language as well as developers debugging object behavior.

1. Properties Are Key–Value Entries

An object property associates a key with a value. Keys are strings or symbols; when you write a number-like key such as obj[7], JavaScript converts it to the string "7". Values can be any JavaScript value, including functions, other objects, and undefined.

Use dot notation when the key is a known identifier, as in user.name, and bracket notation when it is stored in a variable or contains characters that are not valid in an identifier, as in user[field] or user["first-name"]. Reading a missing property returns undefined; it does not automatically create that property. Assignment, by contrast, usually creates or updates an own property: user.name = "Mina".

2. Own Properties and Inherited Properties Differ

An own property is stored directly on the object. An inherited property is found by looking up the object’s prototype chain. For example, const child = Object.create({kind: "bird"}); child.name = "Wren"; gives child an own name property, while kind comes from its prototype.

The in operator checks both own and inherited properties, so "kind" in child is true. To check only the object itself, use Object.hasOwn(child, "kind"), which is safer than calling a potentially overridden child.hasOwnProperty. This distinction matters when validating input, copying data, and iterating over object keys.

3. Property Descriptors Control Behavior

Ordinary data properties have three descriptor flags: writable, enumerable, and configurable. Properties created by assignment are generally writable, enumerable, and configurable. You can inspect a property with Object.getOwnPropertyDescriptor(obj, "key"), or define one with Object.defineProperty.

For example, Object.defineProperty(settings, "version", {value: 1, enumerable: false}) creates a non-enumerable property; because omitted flags default to false in a descriptor, it is also non-writable and non-configurable here. Non-enumerable properties are skipped by common enumeration tools such as Object.keys and for...in. Descriptors are useful when an API needs controlled, read-only, or intentionally hidden properties, but they can make objects less straightforward to inspect.

4. Getters and Setters Are Accessor Properties

An accessor property uses a getter and/or setter instead of storing a value directly. A getter can compute a value when it is read, while a setter can validate or transform a value when it is assigned. For instance, an object could expose get fullName() that combines first and last, so callers use person.fullName like a regular property.

Accessors are useful for derived values and keeping a stable interface while changing internal representation. They should not hide expensive work or surprising side effects: a property read looks simple, so code that performs network requests or mutates unrelated state inside a getter is difficult to reason about. A property cannot be both a data property and an accessor property at once.

5. Prototypes Provide Delegation, Not Copying

Every ordinary object has an internal prototype link, accessible for inspection with Object.getPrototypeOf(obj). When a property is not found on the object itself, JavaScript searches that link, then the next prototype, continuing until it reaches null. A method shared on a prototype is therefore reused through delegation rather than copied onto every instance.

JavaScript classes use this mechanism: methods written in a class body are placed on the class’s prototype, and instances delegate method lookup to it. Prefer class syntax or Object.create when setting up delegation; changing an existing object’s prototype with Object.setPrototypeOf can complicate performance and reasoning. Also take care with untrusted keys such as "__proto__" when building objects from input, since prototype-related behavior can create security and correctness problems.

How to Choose

Choose the property mechanism that matches the data’s purpose. Use ordinary own properties for most application data, and use Object.hasOwn when you need to establish that a value belongs directly to an object rather than being inherited. Use descriptors only when enumerability, writability, or configurability is part of the interface contract; their defaults can be restrictive if you omit flags.

Use getters for inexpensive, predictable derived values, and setters when assignment should enforce a clear rule. Use prototypes or classes when multiple objects should share behavior, not merely to avoid writing a few lines. For dictionary-like data with arbitrary user-provided keys, consider Map rather than a plain object; it avoids inherited property names and offers explicit key-value operations.

Frequently Asked Questions

What is the difference between a property and a method?
A method is a property whose value is a function. The distinction is mostly about how the property is used: calling obj.run() invokes the function stored at run.

Does reading an object property change the object?
Reading a normal data property does not. A getter runs code when accessed, however, so it can have side effects if it was written to do so.

Why does Object.keys omit a property?
It returns only the object’s own enumerable string-keyed properties. It omits inherited properties, non-enumerable properties, and symbol keys; use tools such as Reflect.ownKeys when you need all own string and symbol keys.

Can I change an object’s prototype?
Yes, but changing it after object creation is generally discouraged. Prefer creating the object with the intended prototype using Object.create or defining a class.

Is Object.freeze a deep freeze?
No. It prevents changes to an object’s own properties, but nested objects can still be changed unless they are frozen separately. It also does not recursively freeze values reached through the prototype chain.

Final Thoughts

Properties define what an object exposes; descriptors determine how some properties behave; and prototypes explain where inherited behavior comes from. Knowing whether a property is own or inherited, and whether it is data or an accessor, makes JavaScript objects easier to use, inspect, and design safely.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.