Structured data: arrays and objects · Lesson 24 of 77 · concept

Objects: values with names instead of positions

About 60 minutes.

By the end of this lesson you can

  • Say when a name is a better label for a value than a position, and write an object literal.
  • Read and write properties with dot notation and with bracket notation.
  • Say exactly when bracket notation is required and dot notation cannot work.
  • Predict what reading a property that was never set gives you.
  • List an object's keys, values and entries, and know that the keys are strings.

When a position stops being a good label

Why it matters

An array is the right shape when the values are the same kind of thing and their order means something: stops on a route, scores in a game, lines on an invoice. It is the wrong shape the moment the values mean different things.

Imagine storing one person as `['Ada', 36, true]`. What is index 1? You would have to remember, and so would everyone who reads your code, and everyone who adds a fourth value has to insert it in the agreed place forever. The position carries no meaning, so all the meaning lives in your head.

The fix is to label each value with a name instead of a number: `{ name: 'Ada', age: 36, active: true }`. That is an object, and the improvement is not that it can hold more — it is that the code now says what it means without a comment.

What an object is

Explanation

You write an object with curly braces, and inside them a list of `name: value` pairs separated by commas: `const user = { name: 'Ada', age: 36 };`. Each pair is a property. The name on the left is the key, and the thing on the right is the value.

Keys are text. You can write them unquoted when they look like ordinary names, and MDN calls the whole `{ ... }` form an object initializer or object literal. Values can be anything at all — numbers, strings, booleans, `null`, other objects, arrays, even functions.

Unlike an array, an object has no order that you should rely on and no `length`. It is a set of labelled slots, and you reach into it by name.

Two ways to reach a property

Explanation

Dot notation is the one you will write most: `user.name`. You type the key directly after the dot, exactly as it is spelled.

Bracket notation takes an expression instead: `user['name']`. Those two lines do the same thing, because the expression `'name'` evaluates to the string `name`. The difference only appears when the thing in the brackets is not a literal.

Writing to a property uses the same two forms with `=` after them: `user.age = 37` changes an existing property, and `user.city = 'London'` creates one that did not exist. There is no separate syntax for adding — assignment is how properties come into being.

When brackets are the only option

Explanation

MDN sets out the rule plainly: a property name that has a space or a hyphen, that starts with a number, or that is held inside a variable, can only be read with bracket notation. Dot notation needs a literal identifier, and those names are not identifiers.

The third case is the one that matters most in practice. If a variable `key` currently holds the string `'name'`, then `user[key]` reads the `name` property — but `user.key` looks for a property literally spelled k-e-y, which almost certainly does not exist, so you get `undefined` and no warning.

Read it this way and it stops being confusing: after a dot, you are typing the key. Inside brackets, you are computing the key. Whenever the key is decided while the program runs rather than while you type, you need brackets.

A missing property is undefined, and a typo looks identical

A common mistake

MDN states it directly: nonexistent properties of an object have the value `undefined`, and not `null`. Reading `user.email` on an object that has no email is not an error.

That is convenient and it is also the reason a spelling mistake can survive for days. `user.nmae` is `undefined`, exactly like a property you genuinely have not set yet, so nothing distinguishes the typo from the legitimate absence at the point where you made it.

There are two ways to ask whether a property is actually there. `'age' in user` is `true` when the object has that property, whatever its value. `Object.hasOwn(user, 'age')` asks the same question about the object's own properties. Both differ from `user.age !== undefined` in one case: a property that exists and was deliberately set to `undefined`.

Adding, changing and removing properties

Explanation

Objects are not sealed when you create them. `stock.plums = 7` adds a property, assigning to an existing key replaces its value, and `delete stock.pears` removes a property entirely.

This is true even when the object was declared with `const`. `const` protects the name from being pointed at a different value — it does nothing about the contents. `const user = {}; user.name = 'Ada';` is completely legal, and it surprises almost everyone once. Lesson 6 explains exactly why.

Being able to reshape an object freely is powerful and easy to abuse. Code where objects sprout properties in twelve different places is code nobody can predict, which is why Module 9 spends its time on choosing a shape and sticking to it.

Listing what is inside

Explanation

Three built-in functions turn an object into an array, which is the bridge between the two shapes in this module. `Object.keys(obj)` gives an array of the property names, `Object.values(obj)` an array of the values, and `Object.entries(obj)` an array of `[key, value]` pairs.

Because they hand you arrays, everything you learned in the first two lessons applies: `Object.keys(user).length` is how many properties an object has.

One detail to file away. Keys always come back as strings, even if you wrote them as numbers, and keys that look like non-negative integers come first in numeric order regardless of the order you wrote them in. `Object.keys({ 2: 'b', 1: 'a' })` is `['1', '2']`. If ordering matters to you, use an array.

Recap

Recap

An object labels its values with names instead of positions. Dot notation types the key; bracket notation computes it, which is why a key held in a variable needs brackets. Reading a property that is not there gives `undefined`, so a typo and a genuine absence look the same. `Object.keys`, `Object.values` and `Object.entries` turn an object back into arrays.

Worked examples

Every output below was produced by actually running the code in the same sandbox your exercises run in — it is not a prediction.

Dot notation, bracket notation, and the classic mix-up

Four ways of reading the same object, ending with the line that beginners write by accident: a dot in front of a variable name.

1const user = { name: "Ada", "favourite colour": "green" };2 3console.log(user.name);4console.log(user["name"]);5console.log(user["favourite colour"]);6 7const wanted = "name";8console.log(user[wanted]);9console.log(user.wanted);
  • line 1

    A key with a space has to be quoted here, and can only be read with brackets.

  • line 3

    Dot notation: the key is typed literally.

  • line 4

    Bracket notation with a string literal — identical result.

  • line 5

    The only way to reach this key. `user.favourite colour` is not valid.

  • line 8

    Brackets evaluate `wanted` first, giving 'name', then read that key.

  • line 9

    A dot does NOT evaluate anything. This looks for a key spelled w-a-n-t-e-d.

What it prints

AdaAdagreenAdaundefined

Missing, mistyped, and how to tell

A typo and an absent property produce exactly the same value. See what asking directly looks like instead.

1const user = { name: "Ada", age: 36 };2 3console.log(user.age);4console.log(user.agee);5console.log("age" in user);6console.log(Object.hasOwn(user, "agee"));
  • line 4

    A typo. Not an error — just undefined, silently.

  • line 5

    `in` asks whether the key exists, whatever its value.

  • line 6

    Object.hasOwn answers the same question about the object's own properties, and says false for the typo.

What it prints

36undefinedtruefalse

Adding, deleting, and listing what is left

An object being reshaped at runtime, then turned into arrays so you can see exactly what it now contains.

1const stock = { pears: 4, apples: 12 };2 3stock.plums = 7;4delete stock.pears;5 6console.log(Object.keys(stock));7console.log(Object.values(stock));8console.log(Object.entries(stock));
  • line 3

    Assignment creates the property. There is no add method.

  • line 4

    delete removes it completely — not the same as setting it to null.

  • line 6

    Keys come back as an array of strings, in insertion order here.

  • line 8

    entries pairs each key with its value, giving an array of two-element arrays.

What it prints

["apples","plums"][12,7][["apples",12],["plums",7]]

Check yourself

Not scored, not stored. Getting one wrong is the useful part.

A property name is held in a variable called `key`. How do you read that property from `settings`?

What does this print?

const book = { title: "Emma" };console.log(book.title);console.log(book.titel);

What does `Object.keys({ 2: 'b', 1: 'a' })` give you?

What does this print?

const point = { x: 1 };point.y = 2;console.log(point);console.log(Object.keys(point).length);

Write it yourself

Exercise · intro · 8 tests

Read, write, and ask whether a property is there

Finish three functions that work on the `profile` object. `displayName()` returns the first and last name with a single space between them. `setNickname(value)` stores `value` on `profile` under the property name `nickname`, creating it if it is not there. `hasField(name)` returns true when `profile` has a property with the name held in `name`, and false when it does not.

What your code must do

hasField receives the property name as a string argument, so it cannot be written with dot notation. setNickname returns nothing; its job is the change it makes. displayName must keep working after a nickname has been set.

Define profile, displayName, setNickname and hasField at the top level of your code — the tests call them by name.

Runs on your device in a sandbox with no network and no access to this page.

Exercise · core · 7 tests

Looking things up by a name you are given

A menu is an object whose keys are item names and whose values are prices. Write `priceOf(menu, item)`, which returns the price of that item or 0 when the menu does not list it; `isOnMenu(menu, item)`, which returns true when the menu lists the item — including items that are free; and `countItems(menu)`, which returns how many items the menu lists.

What your code must do

All three receive names as values, never as typed-in keys, and must work for keys containing spaces. An item priced at 0 is still on the menu, so a free item must not be reported as missing.

Define priceOf, isOnMenu and countItems at the top level of your code — the tests call them by name.

Runs on your device in a sandbox with no network and no access to this page.

Worth remembering

  • When must you use bracket notation instead of a dot?

    When the key is held in a variable, or is not a valid identifier — a name with a space or hyphen, or one starting with a digit. A dot types the key; brackets compute it.

  • What do you get from a property an object does not have?

    undefined, not null, and nothing is thrown. A typo therefore looks exactly like a genuinely absent property. Use `in` or Object.hasOwn to ask whether a key exists.

  • How do you get an object's property names, values, or both?

    Object.keys(obj), Object.values(obj), Object.entries(obj). Keys always come back as strings.

Check this lesson against the source

We wrote the explanation; we did not invent the facts. This is the page that backs them.

MDN — Working with objects (JavaScript Guide)

Check there: The sentence that nonexistent properties of an object have value undefined (and not null), and the paragraph listing when bracket notation is required — names with a space or hyphen, names starting with a number, and names held in a variable.

MDN — Property accessors

Check there: That dot notation requires a valid identifier while bracket notation accepts any expression evaluating to a string.

Prefer to read the source in a structured breakdown? Turn this doc into a breakdown

0 of 2 exercises in this lesson solved on this device

Consent version 2026-07-31.1

Cookie preferences