Object basics
Create JavaScript objects, read and change properties with dot or bracket access, check which keys exist, understand property order, and delete properties safely.
- 01Build useful objectsWrite object literals with ordinary, quoted, shorthand, and computed property names.
- 02Read and update propertiesChoose dot or bracket access, change values, and avoid the classic user.field bug.
- 03Inspect object shapeUse in, Object.hasOwn, Object.keys, for...in, and delete with accurate expectations.
Objects group related data
An object is a JavaScript value that groups related values behind names. Those names are called property keys, and the things stored there are property values. Instead of carrying separate variables named userName, userAge, and userRole, you can carry one user object with user.name, user.age, and user.role inside it.
You already met the split between objects and primitives in the Data types lesson, and the Variables lesson showed an important rule: a const object can still have its properties changed. This lesson gives you the daily object moves: create, read, update, check, loop, order, and delete.
An object is one value with named properties. A property key is the label; a property value is the data stored under that label.
Imagine a small filing cabinet for a user account. One drawer is labeled name and contains “Ada”. Another drawer is labeled age and contains 36. When your program needs the age, it opens the age drawer. When it changes the role, it replaces the contents of the role drawer.
- In real life: The cabinet
- In JavaScript: The object value, such as
user - In real life: A drawer label
- In JavaScript: A property key, such as
name - In real life: The contents of a drawer
- In JavaScript: A property value, such as
"Ada" - In real life: Opening a drawer by label
- In JavaScript: Reading
user.nameoruser["name"]
Where the analogy stops: A cabinet is physically copied if you move it. JavaScript objects are shared by reference, which the Objects & references lesson teaches next.
We will stay focused on data properties here. Methods, this, constructors, Symbols, and object-to-primitive conversion all get their own lessons later in Module 8.
Object literals
FOUNDATIONThe most direct way to create an object is an object literal: curly braces containing comma-separated properties. Most properties look like key: value. The key becomes a string property name, and the value can be any JavaScript value: string, number, boolean, null, array, another object, or even a function later.
const user = { name: "Ada", "favorite color": "blue", profile: { city: "Pune" },};Line 2 uses a key that is a valid identifier, so it can be written as name. Line 3 uses a key with a space, so the key must be quoted. Line 4 stores another object as the value of profile. The comma after the last property is a trailing comma; it is allowed and makes future edits tidy.
const user = { profile: { city: "Pune" } };console.log(user.profile.city);console.log(user.settings?.theme);Property names can be any string, even strings that are awkward to type after a dot. Values are just values. A nested object is not magic; it is simply an object stored inside another object. If a middle property may be missing, use the ?. pattern from the Nullish & optional chaining lesson to avoid trying to read through undefined.
Dot vs bracket access
INTERACTIVEThere are two everyday ways to read or write a property. Dot access is for a key you know by name in your source code: user.name. Bracket access is for a key written as a string or stored in a variable: user["favorite color"] or user[field].
If you know the drawer is called name, walk straight to it. That is dot access. If someone hands you a sticky note that says which drawer to open, you must read the note first. That is bracket access with a variable.
- In real life: You know the drawer label by heart
- In JavaScript: Use
user.name - In real life: The label is written on a sticky note
- In JavaScript: Use
user[field] - In real life: The label contains spaces or dashes
- In JavaScript: Use
user["favorite color"]
Where the analogy stops: The analogy hides syntax details: after a dot, JavaScript requires an identifier-like name, but bracket expressions can compute almost any property key.
const user = { name: "Ada", age: "36", role: "admin",};user[key] = value;delete user[key];key in user;Object.hasOwn(user, key);Start with the object, choose a key, then add, change, or delete a property.
Try typing favorite color as the key and blue as the value. Dot access cannot spell that key directly, but bracket access can. Try typing key as a key too: then user.key will stop being undefined, because you really created a drawer labeled “key”.
Predict each line before you step. Change field and watch only line 5 change; line 6 keeps looking for a key literally named field.
script
const field = "age";console.log(user.name);console.log(user["favorite color"]);console.log(user[field]);console.log(user.field);The classic beginner bug is line 6: user.field feels like it should use the variable field, but dot access never does that. It looks for a property whose actual key is the string "field". If the key is data, use brackets.
user.nameuser["first-name"]user[key]user.2user["2"]user.class
Sort each expression. Ask: is the key a valid dot name, a string/variable that needs brackets, or invalid syntax?
Computed & shorthand properties
STEP THROUGHObject literals have two shortcuts you will see constantly. A computed property name uses brackets inside the literal: { [key]: value }. JavaScript evaluates key and uses the result as the property name. A shorthand property lets { name } mean { name: name } when a variable and property share the same name.
Shorthand and computed property names are just two compact ways to write ordinary properties.
script
const value = "blue";const name = "Ada";const age = 36;const user = { name, age, [key]: value };console.log(user.name);console.log(user["favorite color"]);After line 5 runs, there is nothing special about the resulting properties. The object simply has keys named name, age, and favorite color. Later, Methods & this will add method shorthand to this family of object literal conveniences.
In an object literal, { key: value } creates a key literally named key. { [key]: value } reads the variable first. Those brackets are the difference between a label and a computed label.
in and Object.hasOwn
COMPAREReading a property answers “what value do I get?” Sometimes you need a different question: “does this property exist?” That matters because a present property can intentionally store undefined. It also matters because ordinary objects inherit built-in properties such as toString.
const user = { name: "Ada", age: undefined };console.log("age" in user);console.log(Object.hasOwn(user, "age"));console.log(user.age === undefined);console.log("toString" in user);console.log(Object.hasOwn(user, "toString"));| Expression | Result | What it proves |
|---|---|---|
| "age" in user | true | The key exists even though its value is undefined. |
| Object.hasOwn(user, "age") | true | age is an own property directly on user. |
| user.age === undefined | true | This is true for present-undefined and for missing keys, so it cannot prove existence. |
| "toString" in user | true | in also sees inherited properties from Object.prototype. |
| Object.hasOwn(user, "toString") | false | hasOwn ignores inherited properties. |
Use Object.hasOwn(obj, key) when you want to know whether the object itself owns a property. Use key in obj when you intentionally care about inherited properties too. Avoid using obj[key] === undefined as an existence check unless you truly do not care about the difference between missing and present with value undefined.
Property order
STEP THROUGHObjects are not arrays, so do not use them when order is the main point. Still, JavaScript does define the order you get from common operations such as Object.keys and for...in: integer-like keys first in ascending numeric order, then other string keys in insertion order. Symbol keys come after those, and Symbols have their own lesson.
Step through the writes, then compare the final Object.keys order with the order the assignments appeared in.
script
codes.name = "Ada";codes[20] = "twenty";codes[3] = "three";codes["01"] = "leading zero";codes.added = "last";console.log(Object.keys(codes).join(" → "));Notice that 3 appears before 20 even though line 4 ran after line 3. Those property names are array-index-like strings. The key "01" is not the canonical string for the number 1, so it behaves like a normal string key and stays where it was inserted among other strings.
The for…of & for…in lesson introduced loops over keys. The same caution applies here: if your logic depends on ordering, use an array of records rather than one object whose key order carries meaning.
Deleting properties
STEP THROUGHThe Rest of the operators lesson introduced delete. On an object property, delete obj.key removes the property. That is different from assigning undefined, which leaves the property in the object with a value of undefined.
Compare setting a property to undefined with deleting it. The key list and in checks tell the truth.
script
user.mood = undefined;console.log(Object.keys(user).join(", "));delete user.age;console.log(Object.keys(user).join(", "));console.log("age" in user);console.log("mood" in user);Use delete when “this object no longer has that fact” is the truth you want the object to represent. Use obj.key = undefined only when the key should still exist and the value really is unknown, empty, or intentionally unset.
const user = { name: "Ada" }; prevents reassigning the variable user to a different object. It does not prevent user.name = "Grace" or delete user.name. Freezing objects is a separate topic.
Where you’ll use objects
Objects shine whenever names matter. A settings object is clearer than a pile of separate variables because each value travels with a label. Form data, server responses, feature flags, translation dictionaries, lookup tables, and component state all commonly start as objects.
const settings = { theme: "dark", notifications: true, shortcuts: { save: "⌘S" },}; const field = "theme";console.log(settings[field]);console.log(settings.shortcuts?.save);The same rules apply in real code: dot access for a known property, brackets for a dynamic property, optional chaining for a nested value that might not exist, and Object.hasOwn when you need to distinguish missing from present.
| Situation | Question | Best tool | Why |
|---|---|---|---|
| Could the value be undefined? | Does this key exist on the object itself? | Object.hasOwn(obj, key) | It ignores inherited properties and does not confuse missing with present-but-undefined. |
| Include inherited properties? | Does this key exist anywhere on the object chain? | key in obj | Useful when you intentionally care about built-in or inherited behavior. |
| Need the value? | What content is stored here? | obj[key] | Reading the value is different from proving that the key exists. |
Common misconceptions
const user = { age: 36 };const field = "age";console.log(user[field]);console.log(user.field);user.age = undefined;console.log(Object.hasOwn(user, "age"));- “Dot access reads variables.” It does not.
user.fieldmeans the key is literally"field". Useuser[field]for a variable key. - “If the value is undefined, the property is missing.” A property can exist with value
undefined. UseObject.hasOwnto check existence. - “
inandObject.hasOwnare the same.”inincludes inherited properties;Object.hasOwnchecks only the object itself. - “Property order is exactly the order I typed.” Integer-like keys are reported first in numeric order.
- “
deletejust empties the value.”deleteremoves the key. Assigningundefinedempties the drawer but keeps the label. - “A
constobject cannot change.”constprotects the variable binding, not the contents of the object.
Practice exercises
5 EXERCISESIn your editor or console, create a book object with title, author, pages, and a nested status object with read: false.
// Create a book object with title, author, pages, and a nested status object.const book = {
title: "Eloquent JavaScript",
author: "Marijn Haverbeke",
pages: 472,
status: { read: false },
};The object groups related facts under one name. status is a nested object, and the trailing comma is allowed.
Read the program and predict the three console lines.
const user = { name: "Ada", "first-name": "Ada", age: 36 };
const key = "age";
console.log(user.name);
console.log(user[key]);
console.log(user.key);The program prints Ada, then 36, then undefined. Bracket access uses the variable; dot access does not.
Replace the broken expression with the one that prints 36.
const user = { name: "Ada", age: 36 };
const field = "age";
console.log(user.field); // should print 36console.log(user[field]);user[field] reads the variable field, gets "age", and then reads user.age.
What number does the program print?
const profile = { name: "Asha", age: 36, city: "Pune" };
let count = 0;
for (const key in profile) {
if (Object.hasOwn(profile, key)) {
count = count + 1;
}
}
console.log(count);The object has three own properties: name, age, and city, so the program prints 3.
Predict the two key lists. Write them as “first then second”.
const item = { label: "Hat", price: 20 };
item.price = undefined;
console.log(Object.keys(item).join(","));
delete item.price;
console.log(Object.keys(item).join(","));The first key list is label,price because price still exists. The second is label because delete removed price.
Check your understanding
8 QUESTIONSQuestion 1 of 8Which line creates an object with two properties?
Choose an answer to see the explanation.
Question 2 of 8What does bracket access with a variable print?
Read the code, then predictconst user = { name: "Ada", age: 36 }; const field = "age"; console.log(user[field]);Choose an answer to see the explanation.
Question 3 of 8What does dot access with the word field print?
Read the code, then predictconst user = { age: 36 }; const field = "age"; console.log(user.field);Choose an answer to see the explanation.
Question 4 of 8Which literal uses a computed property name?
Choose an answer to see the explanation.
Question 5 of 8What does Object.hasOwn print for an undefined value?
Read the code, then predictconst user = { age: undefined }; console.log(Object.hasOwn(user, "age"));Choose an answer to see the explanation.
Question 6 of 8What order does Object.keys print here?
Read the code, then predictconst codes = { 20: "twenty", 3: "three", name: "Ada" }; console.log(Object.keys(codes).join(","));Choose an answer to see the explanation.
Question 7 of 8What does in print after assigning undefined?
Read the code, then predictconst item = { name: "Hat", price: 20 }; item.price = undefined; console.log("price" in item);Choose an answer to see the explanation.
Question 8 of 8Which statement removes the price property from item?
Choose an answer to see the explanation.
Key takeaways
- Object literals create one value with named properties.
- Use dot access for known identifier keys and bracket access for strings or variable keys.
- Computed names
{ [key]: value }and shorthand{ name }create ordinary properties. Object.hasOwnchecks own properties;inalso sees inherited ones.Object.keyslists integer-like keys first, then other strings in insertion order.deleteremoves a property; assigningundefinedkeeps the key.
Final definition: An object is a JavaScript value that stores related values under property keys you can create, read, update, check, loop over, and remove.
Up next: Objects & references, where you’ll learn why two variables can point at the same object.