Course outline · 0% complete

0/29 lessons0%

Course overview →

Nesting and iterating objects

lesson 5-2 · ~10 min · 15/29

Objects inside objects

Real data nests. A student has grades, grades have subjects:

const student = {
  name: "Ada",
  grades: { math: 95, cs: 99 }
};

console.log(student.grades.math);  // 95

Chain the dots one level at a time. If a middle link might be missing, student.grades?.math answers undefined instead of crashing (the optional chaining operator ?.).

Looping over properties

Objects are not directly for...of iterable. Instead, three helpers turn an object into an array first:

  • Object.keys(obj) → array of key strings
  • Object.values(obj) → array of values
  • Object.entries(obj) → array of [key, value] pairs

With entries you can unpack each pair right in the loop header, like Python's for k, v in d.items():

for (const [subject, grade] of Object.entries(student.grades)) {
  console.log(`${subject}: ${grade}`);
}

The [subject, grade] part is called destructuring: it splits a two-item array into two named variables.

studentname: "Ada"gradesmath: 95cs: 99student.namestudent.grades.math
Nested objects form a tree. Each dot in student.grades.math walks one level down.

Reaching into a nest and looping over it

Three techniques on one nested object: chained dots to read a value two levels down, Object.entries to drive a loop over the inner object, and Object.keys to list the outer property names.

const student = {
  name: "Ada",
  grades: { math: 95, cs: 99 }
};

console.log(student.grades.math);

for (const [subject, grade] of Object.entries(student.grades)) {
  console.log(`${subject}: ${grade}`);
}

console.log(Object.keys(student));

Output

95
math: 95
cs: 99
[ 'name', 'grades' ]

student.grades.math is read left to right, one dot at a time: student gives an object, .grades gives the inner object, and .math gives the number. The loop produces two lines because grades has two properties, and the pair [subject, grade] arrives already split into two usable names.

The final line is a reminder about levels. Object.keys(student) lists only the top-level names, name and grades, and does not descend into the nested object. Every one of these helpers works on exactly one level at a time.

One line of output per property

Formatting a price list is the everyday use of Object.entries, since both halves of each pair are needed, the item name for the label and the price for the value.

const prices = { coffee: 3, tea: 2.5 };

for (const [item, price] of Object.entries(prices)) {
  console.log(`${item} costs $${price}`);
}

Output

coffee costs $3
tea costs $2.5

The double dollar sign in $${price} looks like a typo and is not. The first $ is an ordinary character being printed, part of the money format, and the second one belongs to the ${...} placeholder that follows it. Reading it as $ plus ${price} makes it obvious.

Note also that 2.5 prints as 2.5 rather than 2.50. Numbers carry no formatting of their own, so aligning money to two decimal places is a separate job, handled by the toFixed method covered in lesson 8-2.

Totaling values when the keys do not matter

Summing a cart needs the prices and nothing else, so Object.values is the right helper. It hands back a plain array, which the for...of loop from lesson 3-3 then walks with the accumulator pattern.

const cart = { coffee: 3, bagel: 2.5, juice: 4 };

let total = 0;
for (const price of Object.values(cart)) {
  total = total + price;
}
console.log(total);

Output

9.5

Object.values(cart) is the array [3, 2.5, 4], and once that array exists nothing about the loop is object-specific. That is the mental model to carry away from these three helpers: they convert an object into an array so that everything you already know about arrays applies.

Choosing between them comes down to what the body of the loop needs.

HelperReturns for {coffee: 3, tea: 2.5}Use when
Object.keys['coffee', 'tea']only the names matter
Object.values[3, 2.5]only the contents matter
Object.entries[['coffee', 3], ['tea', 2.5]]both matter

Getting key and value together

The call that returns an array of [key, value] pairs is Object.entries(obj), and it is the closest match to Python's dict.items().

Its pairs are ready for destructuring in a for...of header, which is why for (const [k, v] of Object.entries(obj)) reads so much like the Python loop it replaces. The two neighbouring helpers each give you half of that: Object.keys returns only the names and Object.values only the contents. There is no .items() method on a JavaScript object, so that spelling is one to unlearn coming from Python.