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.
- 01Make objectsWrite object literals with plain keys, quoted keys, shorthand properties, and computed keys.
- 02Read and change propertiesChoose a dot or square brackets, change values, and avoid the common
user.fieldmistake. - 03Check what an object holdsUse
in,Object.hasOwn,Object.keys,for...in, anddelete, and know what each one gives you.
Objects group related data
An object is one value that holds several related values. Each value is stored under a name.
Say you want to keep three facts about a user. You could make three separate variables: userName, userAge, and userRole. Or you can make one user object and keep all three inside it, as user.name, user.age, and user.role.
Each thing stored in an object is called a property. A property has two parts:
- The key is the property's name, like
name. It is also called the property name. - The value is what is stored under that name, like
"Ada".
user, holds two properties. Each property has two parts: the key is its name, like name, and the value is what is stored under it, like "Ada".You met objects in the Data types lesson. There you saw that an object is not a primitive. A primitive is a single simple value, like a number or a string. The Variables lesson showed that you can change an object's properties, even when the object is stored in a const.
This lesson shows the everyday things you do with an object:
- make one,
- read and change its properties,
- check whether a property exists,
- see the order of its keys,
- and delete a property.
An object is one value with named properties. A property key is the name. A property value is what is stored under that name.
Picture a small filing cabinet for one user. One drawer has the label name. Inside it is a paper that says "Ada". Another drawer has the label age. Inside it is a paper that says 36. To find the age, you open the drawer labelled age. To change the role, you swap the paper in the drawer labelled role.
- In real life: The cabinet
- In JavaScript: The object, like
user - In real life: The label on a drawer
- In JavaScript: A key, like
name - In real life: The paper inside a drawer
- In JavaScript: A value, like
"Ada" - In real life: Open the drawer with that label
- In JavaScript: Read
user.nameoruser["name"]
This lesson is about properties that store data. Later lessons in Module 8 cover the rest:
- methods, which are functions stored in an object, and
this, - constructors, which make many objects of the same shape,
- Symbols, a special kind of key,
- and how an object turns into a primitive, like a string.
Object literals
FOUNDATIONThe simplest way to make an object is an object literal. "Literal" means you write the value straight into your code. An object literal looks like this:
- It starts with
{and ends with}. - Inside are the properties, with a comma after each one.
- Most properties are written as
key: value.
The key is always stored as a string. The value can be any JavaScript value: a string, a number, a boolean, null, an array, or even another object.
const user = { name: "Ada", "favorite color": "blue", profile: { city: "Pune" },};console.log(user.name);console.log(user["favorite color"]);Line 2 uses the key name. It is a valid identifier: a name made of letters, digits, _, or $ that does not start with a digit. So it needs no quotes.
Line 3 uses the key favorite color. A key can be any string, even one with a space. But this key is not a valid identifier, so it must be written in quotes.
Line 4 stores another object as the value of profile. The comma at the end of line 4, after the last property, is called a trailing comma. It is allowed, and it makes it easier to add another property later.
Line 6 prints Ada. Line 7 reads the key with the space using square brackets and prints blue. You'll see why it needs square brackets in the next section.
After an object exists, you can add or change a property with =:
- If the key is new, JavaScript adds a new property.
- If the key is already there, JavaScript replaces its value.
This is useful for a shopping cart, a form, or a profile that gets more details later.
const cart = { total: 3 };cart.items = 1;cart.total = 5;console.log(cart.items);console.log(cart.total);The cart starts with one property, total. Line 2 adds items, because the cart did not have that key yet. Line 3 replaces the old total, 3, with 5. Lines 4 and 5 print 1 and 5. It is still the same cart: setting a property never makes a second object.
const order = { drink: "tea", drink: "coffee" };console.log(order.drink);Here the key drink appears twice in one object literal. The object still gets only one drink property, and it keeps the last value. So line 2 prints coffee. Give each key only once. A repeated key is almost always a mistake, so fix it when you see one.
const user = { profile: { city: "Pune" } };console.log(user.profile.city);console.log(user.settings?.theme);An object stored inside another object is called a nested object. Line 2 reads user.profile first, then city inside it. It prints Pune.
Line 3 reads user.settings, which does not exist. The ?. after it means: "if the value on the left is undefined or null, stop here and give undefined." So line 3 prints undefined. Without ?., reading theme from undefined would throw a TypeError. You learned ?. in the Nullish & optional chaining lesson.
Dot or square brackets
INTERACTIVEThere are two ways to read or write a property:
- Dot access, like
user.name. Use it when you know the key while you write the code, and the key is a valid identifier. - Bracket access, like
user["favorite color"]oruser[field]. Inside the square brackets goes a string, or a variable that holds the key.
const user = { name: "Asha" };const key = "name";console.log(user[key]);Line 2 stores the text "name" in the variable key. That is the name of the property, not its value. On line 3, JavaScript first reads key and gets "name". Then it reads the name property of user. It prints Asha.
If you know the drawer is called name, you go straight to it. That is dot access. Sometimes someone hands you a sticky note that says which drawer to open. You read the note first, then open that drawer. That is bracket access with a variable.
- In real life: You know the drawer's label by heart
- In JavaScript: Use
user.name - In real life: A sticky note says which drawer to open
- In JavaScript: Use
user[field] - In real life: The label has a space or a dash in it
- In JavaScript: Use
user["favorite color"]
const user = { name: "Ada", age: "36", role: "admin",};const key = "age";const value = "37";user[key] = value;delete user[key];console.log(Object.keys(user).join(", "));Type a key, then add, change, or delete that property.
Try it. Type favorite color as the key and blue as the value, then press Add/change. You can't write that key after a dot, because of the space. Brackets can still read it.
Next, type key as the key and press Add/change. Now user.key shows a value instead of undefined. That is because the object now really has a property named key.
Predict each line before you step. Change field, and only line 5 changes. Line 6 always looks for a key that is the word field.
script
const field = "age";console.log(user.name);console.log(user["favorite color"]);console.log(user[field]);console.log(user.field);Line 6 shows the most common mistake. user.field looks like it should use the variable field. It doesn't: a dot never reads a variable. It looks for a key that is the word "field" itself. This object has no such key, so you get undefined. When the key is stored in a variable, use brackets.
field first and use what it holds, "age". A dot never reads a variable: user.field looks for a key that is the word field, and this object has none.user.nameuser["first-name"]user[key]user.2user["2"]user.class
Sort each expression. Can the key go after a dot? Does it need brackets, because it is a string or a variable? Or is it a syntax error, which means JavaScript can't even read the code?
Computed & shorthand properties
STEP THROUGHObject literals have two shortcuts you will see often:
- A computed property name puts square brackets around the key inside the literal:
{ [key]: value }. JavaScript first works out the value ofkey. Then it uses that result as the property name. - A shorthand property lets you write
{ name }instead of{ name: name }. It works when the variable and the property have the same name.
const field = "drink";const order = { [field]: "tea" };console.log(order.drink);Line 1 stores the text "drink" in field. On line 2, [field] reads that variable, so the object gets a property named drink. You need the square brackets only while you make the key. Line 3 can use a dot, because you know the key is drink. It prints tea.
Shorthand and computed names are two short 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, the properties are ordinary. The object just has the keys name, age, and favorite color. Nothing remembers how they were written. The Methods & this lesson adds one more shortcut: a short way to write a function inside an object.
In an object literal, { key: value } makes a property whose name is the word key. { [key]: value } reads the variable key first and uses what it holds. The square brackets are the only difference.
Check whether a key exists
COMPAREReading a property tells you its value. Sometimes you need to ask something else: does this property exist at all? Reading the value can't always tell you, for two reasons:
- A property can exist and hold the value
undefined. A missing property also reads asundefined. - Ordinary objects inherit some built-in properties, like
toString. Inherited means your object can use the property, but it is stored on another object, not on yours. That other object isObject.prototype; a later lesson explains it.
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"));The table shows what each line prints. Read each row as: "this check prints this, and here is what that tells you."
| The check | What it prints | What it tells you |
|---|---|---|
"age" in user | true | The key exists, even though its value is undefined. |
Object.hasOwn(user, "age") | true | age is a property of user itself. |
user.age === undefined | true | This is also true for a missing key, so it can't tell you whether the key exists. |
"toString" in user | true | in also counts inherited properties, like toString. |
Object.hasOwn(user, "toString") | false | Object.hasOwn skips inherited properties. |
Which check should you use?
- Use
Object.hasOwn(obj, key)to ask: "Does this object itself have this key?" It ignores inherited properties. - Use
key in objwhen inherited properties should count too. - Don't use
obj[key] === undefinedto check whether a key exists. It istruefor a missing key, and also for a key that holdsundefined.
const user = { hasOwnProperty: false };console.log(Object.hasOwn(user, "hasOwnProperty"));Objects also inherit an older method called hasOwnProperty. In older code you may see obj.hasOwnProperty(key). But this object has its own key named hasOwnProperty, and it holds false. So user.hasOwnProperty("name") would throw a TypeError, because false is not a function.
Object.hasOwn belongs to Object, not to your object, so it still works. Line 2 prints true. Use Object.hasOwn in new code.
Property order
STEP THROUGHObjects are not arrays. If order is the main point, use an array. Still, JavaScript has fixed rules for the order of an object's keys. You see this order when you use Object.keys(obj), which gives an array of the object's own keys, or a for...in loop. The rules:
- First come the integer-like keys, from smallest to largest. These are keys like
"3"or"20": whole numbers written the normal way, with no leading zero. - Then come all the other string keys, in the order you added them.
Symbols, a special kind of key, are left out by Object.keys and for...in. Symbols have their own lesson.
Step through the lines that add keys. Then compare the final Object.keys order with the order the lines added them.
script
codes.name = "Ada";codes[20] = "twenty";codes[3] = "three";codes["01"] = "leading zero";codes.added = "last";console.log(Object.keys(codes).join(" → "));Look at the result. 3 comes before 20, even though line 4 added 3 after line 3 added 20. Both are integer-like keys, so they go first, smallest first.
The key "01" is different. It has a leading zero, so it is not the normal way to write the number 1. JavaScript treats it as an ordinary string key. It stays in the order it was added, after name.
3 and 20 are integer-like, so Object.keys lists them first, smallest first. The other keys, name, 01, and added, follow in the order they were added.The for…of & for…in lesson showed loops over keys. The same advice applies here: if your code depends on order, use an array of objects. Don't rely on the key order of one object.
Deleting properties
STEP THROUGHThe Rest of the operators lesson introduced delete. delete obj.key removes the property from the object. That is not the same as setting it to undefined:
obj.key = undefinedkeeps the key. Only its value changes, toundefined.delete obj.keyremoves the key and its value.
undefined keeps the key; only the value changes. delete takes the whole property out, key and value.Compare setting a property to undefined with deleting it. The list of keys and the in checks show the difference.
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 the object should no longer have that property. Use obj.key = undefined only when the key should stay, but it has no value right now.
const user = { name: "Ada" }; stops you from giving user a new value, like user = {}. It does not stop you from changing the object's properties. You can still write user.name = "Grace" or delete user.name. Stopping all changes is called freezing an object, and that is a separate topic.
Where you’ll use objects
Use an object whenever names matter. A settings object is clearer than many separate variables, because each value has its name right next to it. These often start as objects:
- the values someone typed into a form,
- data that a server sends back,
- feature flags, which switch parts of an app on or off,
- lists of translations, from a word to the same word in another language,
- and the current state of a part of the page.
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 here:
- Brackets for a key in a variable:
settings[field]on line 8 printsdark. - A dot for a key you know, and
?.for a nested value that might be missing: line 9 prints⌘S.
const response = { name: "Asha", city: "Delhi" };const city = Object.hasOwn(response, "city") ? response.city : "Not set";console.log(city);Data from a server or a form may leave out fields that are optional. Line 2 uses the conditional operator: test ? a : b gives a when the test is true, and b when it is false. Here the test is Object.hasOwn(response, "city"):
- If
cityis there,citygetsresponse.city. - If it is missing,
citygets"Not set".
This response has a city, so line 3 prints Delhi.
The table below helps you pick a tool. Read each row as: "in this situation, ask this question, and use this tool."
| Situation | Question | Best tool | Why |
|---|---|---|---|
The value might be undefined | Does the object itself have this key? | Object.hasOwn(obj, key) | It skips inherited properties. It tells a missing key apart from a key that holds undefined. |
| Inherited properties should count | Can the object use this key, from itself or from where it inherits? | key in obj | Use it when built-in or inherited properties matter to you. |
| You need the value | What is stored under this key? | obj[key] | It gives the value. It does not tell you whether 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"));Line 3 prints 36. Line 4 prints undefined. Line 6 prints true, even though line 5 set age to undefined. Each belief below is a common mistake, followed by what really happens.
- "A dot reads variables." It doesn't.
user.fieldlooks for a key that is the word"field". Useuser[field]when the key is stored in a variable. - "If the value is undefined, the property is missing." Not always. A property can exist and hold
undefined. UseObject.hasOwnto check whether it exists. - "
inandObject.hasOwnare the same." They are not.inalso counts inherited properties.Object.hasOwnchecks only the object itself. - "Keys always come out in the order I typed them." Integer-like keys come out first, smallest first.
- "
deletejust empties the value."deleteremoves the key too. Setting a property toundefinedkeeps the key and changes only the value. - "A
constobject can't change."constonly stops you from giving the variable a new value. The object's properties can still change.
Practice exercises
5 EXERCISESIn your editor or the console, make a book object with title, author, and pages. Also give it a nested status object that holds 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 keeps related facts under one name. status is a nested object. The comma after the last property is allowed.
Read the program. Predict the three lines it prints.
const user = { name: "Ada", "first-name": "Ada", age: 36 };
const key = "age";
console.log(user.name);
console.log(user[key]);
console.log(user.key);It prints Ada, then 36, then undefined. Brackets use what the variable key holds. A dot does not.
Replace the broken expression with 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 and gets "age". Then it reads user.age, which is 36.
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 keys of its own: name, age, and city. So it prints 3.
Predict the two lists of keys. 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 list is label,price, because price still exists. The second list is label, because delete removed price.
Check your understanding
8 QUESTIONSQuestion 1 of 8Which line makes an object with two properties?
Choose an answer to see the explanation.
Question 2 of 8What does this bracket read 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 this dot read 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 object literal uses a computed property name?
Choose an answer to see the explanation.
Question 5 of 8What does Object.hasOwn print for a key that holds undefined?
Read the code, then predictconst user = { age: undefined }; console.log(Object.hasOwn(user, "age"));Choose an answer to see the explanation.
Question 6 of 8In what order does Object.keys list these keys?
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 a property is set to 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
- An object literal makes one value with named properties.
- Use a dot when you know the key and it is a valid identifier. Use square brackets when the key is in a variable, or has a space or a dash.
- A computed name
{ [key]: value }and a shorthand{ name }both make ordinary properties. Object.hasOwnchecks only the object's own properties.inalso counts inherited ones.Object.keyslists integer-like keys first, smallest first. The other keys follow, in the order you added them.deleteremoves a property. Setting it toundefinedkeeps the key.
Final definition: An object is a JavaScript value that keeps related values under names, called keys. You can add, read, change, check, list, and remove its properties.
Up next: Objects & references. You'll learn why two variables can point to the same object.