3.5 Objects and Properties

Aligned outcomes:

SLO 2

Describe the principles of structured programming.

Related values belong under one name. An object replaces a scatter of parallel variables with a single structured record, and reaching a property by dot or by computed key is the array-index idea applied to names instead of positions.

SLO 3

Describe, design, implement, and test structured programs using currently accepted methodology.

Options objects and destructuring are the accepted way to give a function many inputs without a long unreadable argument list. Methods — a property whose value is a function — are the first step toward the object-oriented work later chapters take up.

Learning Objectives

By the end of this section you should be able to:

In this section, you will learn to:
  • Create an object literal that groups related values under names.
  • Read, change, add, and remove properties with dot notation.
  • Explain when square brackets are required instead of a dot.
  • Work with objects nested inside objects and inside arrays.
  • Recognize a method as a property whose value is a function.
  • Pass an object of named options to a function.
  • Unpack properties into variables with destructuring.

Section 1.2 split every JavaScript value into two camps: the seven primitives, each holding one thing, and objects, which hold collections. Arrays were your first object — a numbered list. This section is about the other kind: a collection where each value has a name instead of a number.

Here is the problem objects solve. Suppose you are describing a student:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

Marisol, 19, from Chico

Three variables, related only by the fact that you named them carefully. Nothing in the program says they belong together. Add a second student and you have six variables and a naming problem.

An object groups them into one value:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

Marisol, 19, from Chico
{"name":"Marisol","age":19,"city":"Chico"}

The braces make an object literal. Inside, each line is a key: value pair — the key on the left names the value on the right. Pairs are separated by commas.

Definition 3.5.1: Object

An object is a value that holds a collection of named values. It is written as an object literal using braces, with each entry a key: value pair.

An array answers "which position?" and an object answers "which name?". If the things you are storing are interchangeable items of the same kind — scores, names, prices — you want an array. If they are different facts about one thing — a name, an age, a city — you want an object. Most real programs nest the two, as Section 3.5.4 shows.

Definition 3.5.2: Property

A property is one key: value pair belonging to an object. The key names it, and the value can be of any type — including another object or a function.

3.5.2 Reading and Changing Properties

You read a property with a dot and its name:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

Eloquent JavaScript
472

You change one by assigning to it, and you add one exactly the same way:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

{"title":"Eloquent JavaScript","pages":480,"author":"Haverbeke"}

Note that book was declared with const and both lines worked. const prevents book from being pointed at a different object; it does not freeze the object's contents. That distinction is the subject of Section 3.6.

delete removes a property entirely:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

{"title":"Eloquent JavaScript"}
undefined

Reading a property that is not there is not an error — it gives undefined. That is worth remembering, because it means a typo in a property name fails silently:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

Marisol
undefined

Compare that with an undeclared variable, which throws a ReferenceError you cannot miss (Section 2.5.3). A misspelled property just hands back undefined, and the program carries on until that undefined causes trouble somewhere else entirely. When a value is mysteriously undefined, check the spelling of the property name before anything else.

Concepts in Practice: Properties

1. What does this print?

Editor
runs in your browser
▶ Press Run to see the output…
  1. blue then undefined
  2. blue then an error
  3. An error on the assignment, because color was not in the literal
Solution

a. blue then undefined.

Assigning to a property that does not exist creates it. Reading one that does not exist gives undefined rather than an error.

Try It Now 3.5.1

Create an object phone with properties brand and price. Print the brand, change the price, add a property inStock set to true, then print the whole object.

Editor
runs in your browser
▶ Press Run to see the output…
Solution
Editor
runs in your browser
▶ Press Run to see the output…

Output:

Pixel
{"brand":"Pixel","price":549,"inStock":true}

3.5.3 Square Brackets and Computed Keys

Dot notation needs a name you can type literally. Two situations break it.

A key that is not a simple word:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

14
dark

settings.font size is not valid JavaScript — the space ends the name. Square brackets take a string, so any key at all is reachable.

A key you do not know until the program runs:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

19
undefined

This is the difference worth burning in. student[field] looks up the variable field, finds "age", and fetches that property. student.field looks for a property literally named "field", which does not exist.

Dot means "the property spelled exactly like this". Brackets mean "work out the name first, then fetch it". Whenever the property name lives in a variable — a loop counter, a user's choice, a key read from data — you need brackets. Dot notation cannot express it at all.

That makes it possible to walk over an object's properties:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

name: Marisol
age: 19
city: Chico

Object.keys(student) gives back an array of the object's key names, and student[key] fetches each value. There is no way to write that loop with dot notation.

Concepts in Practice: Dot vs brackets

1. Given const key = "price"; and const item = { price: 10 };, what does item.key give?

  1. 10
  2. undefined
  3. An error
Solution

b. undefined. item.key looks for a property literally named key, which the object does not have. item[key] is the form that gives 10.

Try It Now 3.5.2

Given the object below, print the value of the property whose name is held in the variable wanted, then print every key and value using a loop.

Editor
runs in your browser
▶ Press Run to see the output…
Solution
Editor
runs in your browser
▶ Press Run to see the output…

Output:

16
brand -> Framework
ram -> 16
screen size -> 13

"screen size" could only ever be reached with brackets.

3.5.4 Objects Inside Objects and Arrays

A property's value can be any type — including another object, or an array. This is where objects start describing real data.

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

Chico
CSCI 4
2

Read student.address.city left to right: take student, get its address, get that object's city. Each step is the same operation applied to whatever the previous step produced.

The reverse nesting — an array of objects — is the single most common shape in real programs:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

Marisol: 92
Dev: 78
Priya: 85

students[i] picks one object out of the array; .name reads a property of that object. Every table of records you will ever handle — rows from a spreadsheet, items in a cart, sprites in a game — has this shape.

Example 3.5.1: Finding a record

Combining what you have: a loop, a condition, an early return, and an array of objects.

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

78
null

Returning null for "not found" is a deliberate choice: it is a value that says nothing here out loud, rather than undefined, which is also what a typo produces.

That is the linear search from Section 2.2, now searching real records instead of strings. The algorithm did not change at all — only the shape of the data it walks. This is what Section 2.2 meant by a canonical algorithm being worth learning once.

Try It Now 3.5.3

Given the array below, print each item's name and total cost (price * quantity).

Editor
runs in your browser
▶ Press Run to see the output…
Solution
Editor
runs in your browser
▶ Press Run to see the output…

Output:

Notebook: 12
Pen: 15

Pulling cart[i] into a variable named item first keeps the last line readable.

3.5.5 Methods

A property's value can be a function. Section 3.4 established that a function is a value, so nothing new is needed to allow it:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

I am a counter.
function
Definition 3.5.3: Method

A method is a property whose value is a function. It is called by writing the property access followed by parentheses, as in counter.describe().

You have been calling methods since chapter 1 without the name for them. console.log() is the log method of the console object. "hi".toUpperCase() is a method of a string. [1,2].push(3) is a method of an array.

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

JAVASCRIPT
10
function

Note the difference in the last two lines: length is a plain property, so there are no parentheses. toUpperCase is a method — a property holding a function — so calling it needs (). Leaving them off gives you the function itself, exactly as in Section 3.4.1.

There is more to methods — in particular, how a method refers to the object it belongs to. That needs the keyword this, which arrives with classes in Chapter 5.

Concepts in Practice: Methods

1. What is the difference between word.toUpperCase and word.toUpperCase()?

  1. Nothing; the parentheses are optional.
  2. The first is the function value itself, the second calls it and gives the result.
  3. The first is an error.
Solution

b. Without parentheses you get the function; with them you get what it returns. This is the same rule as Section 3.4.1, now applied to a property.

3.5.6 Objects as Named Arguments

Section 3.2.2 showed that arguments match parameters by position, and that a function taking (width, height) will happily accept them backwards. Once a function needs more than two or three inputs, positional arguments become genuinely hard to read:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

red box, 10x4x6

Reading the call alone, there is no way to tell which number is the height. Pass a single object instead, and every value carries its name to the call site:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

red box, 10x4x6
blue box, 10x4x6

Both calls give the same measurements, because the object's keys — not their order — decide what goes where. The swap bug from Section 3.2.2 cannot happen.

This is the dominant style in the libraries you meet from Chapter 8 onwards. A call like circle({ radius: 10 }) is one function, one argument, and that argument is an object literal. When you see braces inside a function call's parentheses, that is what you are looking at — an object being built on the spot and handed over as a bag of named options.

Try It Now 3.5.4

Write a function makeLabel that takes one options object with text, size, and bold properties and returns a string like "HELLO (14px, bold)" when bold is true and "HELLO (14px)" when it is false. Call it both ways.

Editor
runs in your browser
▶ Press Run to see the output…
Solution
Editor
runs in your browser
▶ Press Run to see the output…

Output:

HELLO (14px, bold)
HELLO (14px)

3.5.7 Destructuring

Reading several properties out of an object gets repetitive:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

Marisol, 19, Chico

Destructuring does all three in one line:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

Marisol, 19, Chico

The braces on the left of the = are not making an object. They are a pattern saying "take the properties called name, age and city, and make variables of those names."

Definition 3.5.4: Destructuring

Destructuring unpacks values out of an object or array into separate variables in a single statement. For objects the variables are matched by property name; for arrays they are matched by position.

You do not have to take everything, and order is irrelevant:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

Marisol lives in Chico

Arrays destructure too, by position rather than by name — square brackets instead of braces:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

x is 10, y is 20

Destructuring a parameter

The two ideas combine. A function taking an options object can unpack it right in the parameter list:

Editor
runs in your browser
▶ Press Run to see the output…

What you should see:

red box, 10x4x6

Compare that with the version in Section 3.5.6: identical behaviour, but the parameter list now documents exactly which properties the function expects, and the body says width rather than options.width throughout.

Concepts in Practice: Destructuring

1. What does this print?

Editor
runs in your browser
▶ Press Run to see the output…
  1. Pen costs 2
  2. 2 costs Pen
  3. An error, because the order does not match
Solution

a. Pen costs 2.

Object destructuring matches by property name, so the order in the pattern makes no difference. Array destructuring is the opposite — there, position is everything.

2. Given const [first, second] = [10, 20];, what is second?

  1. 10
  2. 20
  3. undefined
Solution

b. 20. Arrays destructure by position, so first takes the value at index 0 and second takes the one at index 1.

Try It Now 3.5.5

Rewrite this function so it destructures its parameter, and shorten the body to match.

Editor
runs in your browser
▶ Press Run to see the output…
Solution
Editor
runs in your browser
▶ Press Run to see the output…

Output:

Hi Marisol Rivera!

The call site did not change at all — destructuring is entirely a decision about how the function reads its own argument.

Problem Set 3.5

3.5.1 What does this print, and why is the second line not an error?

Editor
runs in your browser
▶ Press Run to see the output…
Solution

Step 1 — Trace the code line by line: The object literal creates car with two properties: make: "Toyota" and year: 2019.

Step 2 — The assignment car.color = "blue";: Assigning to a property that does not yet exist creates it. So after this line, car has three properties.

Step 3 — The first print: car.color now exists and holds "blue", so the console shows blue.

Step 4 — The second print: Reading a property that is not there is not an error — it gives undefined. There is no model property, so the console shows undefined.

Answer: It prints blue then undefined. The second line is not an error because reading a missing property returns undefined; only reading an undeclared variable throws a ReferenceError.

3.5.2 Given const key = "price"; and const item = { price: 10 };, what does item.key give and what does item[key] give?

Solution

Step 1 — Evaluate item.key: Dot notation looks for a property literally named key. The object { price: 10 } has no such property, so the result is undefined.

Step 2 — Evaluate item[key]: Square brackets evaluate the expression inside first. Here key is the variable holding "price", so JavaScript fetches the property named "price" and gets 10.

Answer: item.key gives undefined (it looks for a property literally named key); item[key] gives 10 (brackets work out the name from the variable first).

3.5.3 What is the difference between word.toUpperCase and word.toUpperCase()?

Solution

Step 1 — word.toUpperCase without parentheses: A method is just a property whose value is a function. Without parentheses you get the function value itself — nothing runs.

Step 2 — word.toUpperCase() with parentheses: The parentheses call the function, so you get its return value, e.g. "JAVASCRIPT" for word = "javascript".

Answer: word.toUpperCase is the function value itself; word.toUpperCase() calls it and gives the result string. The parentheses are what make the call happen.

3.5.4 What does this print, and why does the order in the pattern not matter?

Editor
runs in your browser
▶ Press Run to see the output…
Solution

Step 1 — Destructure the object: const { cost, title } = item; unpacks properties into variables matched by property name: cost becomes 2 and title becomes "Pen".

Step 2 — Print: console.log(title + " costs " + cost) uses those variables in whatever order we like, producing Pen costs 2.

Step 3 — Why order does not matter: Object destructuring matches by name, not position — the pattern { cost, title } says "take the property called cost" wherever it lives in the object. (Array destructuring is the opposite: it matches by position.)

Answer: It prints Pen costs 2. Order in the pattern is irrelevant because object destructuring matches variables to properties by name.

3.5.5 Given const [first, second] = [10, 20];, what is second, and how is the matching rule different from object destructuring?

Solution

Step 1 — Match by position: Array destructuring pairs variables with elements by index: first takes index 0 (10) and second takes index 1 (20).

Step 2 — Compare with objects: Objects match by property name ({ title } grabs the property called title, regardless of where it sits); arrays match purely by position.

Answer: second is 20. Array destructuring matches by position, whereas object destructuring matches by property name.

3.5.6 Create an object phone with brand and price, change the price, add inStock, and print the result.

Solution

Step 1 — Create the object literal: Group the related facts under one name with braces and key: value pairs:

Editor
runs in your browser
▶ Press Run to see the output…

Step 2 — Change the price: Assignment to an existing property overwrites it:

Editor
runs in your browser
▶ Press Run to see the output…

Step 3 — Add inStock: Assigning to a property that does not exist creates it:

Editor
runs in your browser
▶ Press Run to see the output…

Step 4 — Print the whole object:

Editor
runs in your browser
▶ Press Run to see the output…

Output:

{"brand":"Pixel","price":549,"inStock":true}

Answer: The final object is { brand: "Pixel", price: 549, inStock: true }, printed as shown above.

3.5.7 Write a loop that prints every key and value of { a: 1, b: 2, c: 3 } using Object.keys and square brackets.

Solution

Step 1 — Get the key names: Object.keys(obj) returns an array of the object's keys, which a loop can walk through.

Step 2 — Fetch each value with brackets: Inside the loop, the key is held in a variable, so dot notation cannot reach it — square brackets are required.

Editor
runs in your browser
▶ Press Run to see the output…

Output:

a: 1
b: 2
c: 3

Answer: The loop above prints a: 1, b: 2, c: 3 — one line per key/value pair.

3.5.8 Explain why a misspelled property name is harder to spot than a misspelled variable name.

Solution

Step 1 — What happens with a misspelled variable: An undeclared variable throws a ReferenceError immediately when read — loud and impossible to miss.

Step 2 — What happens with a misspelled property: Reading a property that does not exist simply returns undefined. No error is raised at the point of the typo.

Step 3 — Why that is dangerous: The program keeps running, and the undefined travels onward until it causes trouble somewhere else entirely — often far from the actual mistake. You must trace back from the crash site to find the typo.

Answer: A misspelled variable fails immediately with a ReferenceError, but a misspelled property silently yields undefined, letting the bug surface later and far away from its cause.

3.5.9 Given the cart below, print each item's name and total cost.

Editor
runs in your browser
▶ Press Run to see the output…
Solution

Step 1 — Loop over the array of objects: Use an index loop so we can pick one record at a time with cart[i].

Step 2 — Compute the total per item: For each item, multiply price by quantity and print alongside the name.

Editor
runs in your browser
▶ Press Run to see the output…

Output:

Notebook: 12
Pen: 15

Answer: The code prints Notebook: 12 and Pen: 15.

3.5.10 Write findStudent(list, name) that returns the matching object or null, and say why null is a better "not found" value than undefined.

Solution

Step 1 — Write the linear search: Walk the array with an index loop; compare each element's name property against the wanted name using ===; return the whole object on a match.

Step 2 — Handle "not found": If the loop finishes without returning, return null.

Editor
runs in your browser
▶ Press Run to see the output…

Step 3 — Why null beats undefined: undefined is also what you get from a typo or a missing property, so seeing it tells you nothing about why the value is absent. null is a deliberate value meaning "we looked and found nothing" — it distinguishes an intentional empty result from an accidental one.

Answer: The function above returns the matching student object or null; null is preferred because it explicitly signals "not found", whereas undefined could equally indicate a typo or missing property.

3.5.11 Write makeLabel(options) taking text, size, and bold, returning "HELLO (14px, bold)" or "HELLO (14px)".

Solution

Step 1 — Take one options object parameter: Every input arrives named, so the call site reads clearly and argument order cannot cause bugs.

Step 2 — Build the label conditionally: Start the string with text and size, append , bold only when options.bold is true, then close the parenthesis.

Editor
runs in your browser
▶ Press Run to see the output…

Output:

HELLO (14px, bold)
HELLO (14px)

Answer: The function above returns "HELLO (14px, bold)" when bold is true and "HELLO (14px)" when it is false.

3.5.12 Rewrite makeLabel so it destructures its parameter instead of reading options. three times.

Solution

Step 1 — Move the destructuring into the parameter list: Replace options with the pattern { text, size, bold }, which unpacks the three properties into variables of those names the moment the function is called.

Step 2 — Shorten the body: With local variables available, drop every options. prefix.

Editor
runs in your browser
▶ Press Run to see the output…

Output:

HELLO (14px, bold)
HELLO (14px)

Answer: The rewritten function destructures in its parameter list and uses bare text, size, and bold throughout — identical behaviour, cleaner body, and the parameter list now documents exactly which properties are expected.

3.5.13 Give one reason to pass an options object instead of four positional arguments.

Solution

Step 1 — Identify the failure mode of positional arguments: With four positional arguments such as (width, height, depth, color), a caller can swap two numbers and get no error — just silently wrong output, since all values are valid types.

Step 2 — How the options object fixes it: Passing { width: 10, height: 4, depth: 6, color: "red" } means each value carries its own name. Keys decide what goes where, not order, so swapping them in the literal changes nothing.

Answer: One reason: an options object makes each argument self-describing, so the swap bug of positional arguments cannot happen — the keys, not their order, determine which value goes to which use.

3.5.14 An object has a property "due date". Write the two lines that read it and that change it to "Friday".

Solution

Step 1 — Reading it: The key contains a space, so dot notation cannot express it (obj.due date is invalid). Square brackets take a string, so they work:

Editor
runs in your browser
▶ Press Run to see the output…

Step 2 — Changing it: Same rule on assignment — brackets with the quoted key:

Editor
runs in your browser
▶ Press Run to see the output…

Answer: Read it with task["due date"] and change it with task["due date"] = "Friday"; — any key that is not a simple word must be reached with square brackets.

Key Terms

Object -- A value holding a collection of named values, written as an object literal with braces.

Object literal -- The { key: value, ... } syntax for creating an object.

Property -- One key: value pair in an object; the value may be any type, including another object or a function.

Key -- The name of a property. Always a string, even when written without quotes.

Dot notation -- object.name, which reads the property spelled exactly like the text after the dot.

Square bracket notation -- object[expression], which works out the property name first. Required for keys with spaces and for names held in variables.

Method -- A property whose value is a function, called with parentheses as in counter.describe().

Options object -- A single object argument carrying named values, used instead of several positional arguments.

Destructuring -- Unpacking properties into variables in one statement; by name for objects, by position for arrays.

Object.keys() -- Returns an array of an object's property names, which lets a loop walk over them.