---
title: Objects
source: 'https://academia.sh/en/courses/javascript-fundamentals/objects'
course: 'JavaScript Fundamentals'
language: en
updated: '2026-08-17T18:09:46+00:00'
license: 'CC BY-SA 4.0'
---

# Objects

The two forms of property access, key stringification, shorthand and computed syntax, existence checks, destructuring, spread, and reference semantics.

The previous lesson used measurement records as objects, but the syntax was never
defined. This lesson takes up objects: creation, access, separating, and combining.

An object is an ordered set of key–value pairs. Keys are strings or symbols; values can
be of any type. The prototype chain, property descriptors, and class syntax are the next
course's subject; this lesson covers plain data objects.

## Creation and Access

```js
const field = "temperature";
const station = "A1";
const temperature = 21.5;

const record = {
  station,
  temperature,
  [field + "Unit"]: "C",
  summary() {
    return `${this.station}: ${this.temperature}`;
  },
};

console.log(record);
console.log(record.station, record["temperature"], record[field]);
console.log(record.summary());
```

```
{
  station: 'A1',
  temperature: 21.5,
  temperatureUnit: 'C',
  summary: [Function: summary]
}
A1 21.5 21.5
A1: 21.5
```

Three writing shortcuts were used together. **Shorthand property** (`station`) takes its
value from a variable of the same name. **Computed key** (`[field + "Unit"]`) produces
the key at runtime. **Shorthand method** (`summary()`) writes a function property
without the `function` keyword; by the rule from the Arrow Functions lesson, methods are
not written in arrow form.

There are two forms of access. **Dot notation** requires a fixed, valid name. **Bracket
notation** accepts any expression; it is required when the key is determined at
runtime. In the output's second line, all three access forms gave the same value.

The object being written across multiple lines is the runtime's inspection format; once
an object passes a certain length it is split across lines, and function properties are
shown as `[Function: name]`. This display is not defined in the standard.

## Keys Are Strings

Every key except a symbol is converted to a string:

```js
const obj = {};
obj[1] = "number one";
obj["1"] = "text one";
obj[true] = "boolean";
console.log(obj);
console.log(Object.keys(obj));
console.log(typeof Object.keys(obj)[0]);
```

```
{ '1': 'text one', true: 'boolean' }
[ '1', 'true' ]
string
```

`1` and `"1"` are the same key; the second assignment overwrote the first. This is why
the indices that come out of `for...in` in the Loops lesson are strings — an array is
also an object and carries its indices as keys.

If a mapping with numeric keys is needed, the `Map` structure preserves the distinction;
that is outside this course's scope.

## Existence Checks

A field being **absent** and a field carrying the value `undefined` are different
situations:

```js
const record = { station: "A1", humidity: undefined };
console.log(record.humidity, "humidity" in record, Object.hasOwn(record, "humidity"));
console.log(record.pressure, "pressure" in record, Object.hasOwn(record, "pressure"));
delete record.humidity;
console.log("after delete:", "humidity" in record, record);
```

```
undefined true true
undefined false false
after delete: false { station: 'A1' }
```

Reading gave `undefined` in both cases; only the existence check showed the difference.
The `in` operator also counts inherited properties; `Object.hasOwn` looks only at the
object's own properties. This course uses the latter.

`delete` removes the property entirely. Assigning `undefined` leaves the property in
place and only changes its value.

## Key–Value Conversions

Moving back and forth between an object and an array is the basis of writing
transformations:

```js
const record = { station: "A1", temperature: 21.5, humidity: 48 };
console.log(Object.keys(record));
console.log(Object.values(record));
console.log(Object.entries(record));

const pairs = [["station", "B1"], ["temperature", 23]];
console.log(Object.fromEntries(pairs));
```

```
[ 'station', 'temperature', 'humidity' ]
[ 'A1', 21.5, 48 ]
[ [ 'station', 'A1' ], [ 'temperature', 21.5 ], [ 'humidity', 48 ] ]
{ station: 'B1', temperature: 23 }
```

`Object.entries` and `Object.fromEntries` are each other's inverse. This pair makes it
possible to use array methods on an object: the object is converted to an array,
filtered or mapped, then converted back to an object.

## Destructuring

**Destructuring** separates an object's or array's fields into separate names:

```js
const record = { station: "A1", temperature: 21.5, location: { elevation: 120 } };

const { station, temperature: degrees, humidity = null } = record;
console.log(station, degrees, humidity);

const { location: { elevation } } = record;
console.log(elevation);

const { station: name, ...rest } = record;
console.log(name, rest);

const [first, , third = 0] = [21.5, 19.75];
console.log(first, third);
```

```
A1 21.5 null
120
A1 { temperature: 21.5, location: { elevation: 120 } }
21.5 0
```

Four abilities were used: **renaming** (`temperature: degrees`), **default**
(`humidity = null`), **nested destructuring**, and **gathering the remaining fields**.
The default's criterion is the same as in the Parameters lesson: it engages only if the
value is `undefined`.

In array destructuring, order is by position; an element to skip is left blank. This is
the `[index, value]` syntax used with `entries` in the Loops lesson.

## Spread and Combining

Spread syntax copies an object's own enumerable properties into another object literal:

```js
const base = { station: "A1", temperature: 21.5, unit: "C" };
const update = { temperature: 22.75 };

console.log({ ...base, ...update });
console.log({ ...update, ...base });
console.log(base);
```

```
{ station: 'A1', temperature: 22.75, unit: 'C' }
{ temperature: 21.5, station: 'A1', unit: 'C' }
{ station: 'A1', temperature: 21.5, unit: 'C' }
```

**Order determines the result:** a property with the same name written later overwrites
the earlier one. In the second line, the order is reversed, so the update is lost. The
third line shows the original object did not change — spread produces a new object.

The copy is **shallow**:

```js
const deep = { station: "A1", location: { elevation: 120 } };
const copy = { ...deep };
copy.location.elevation = 999;
console.log(deep.location.elevation);
```

```
999
```

The inner object was not copied; the two objects share the same `location` object. Deep
copying is outside this course's scope and will be taken up in the Immutability
Techniques lesson.

## Reference Semantics

Objects are bound to names by reference. The rule established in the Passing by Value
and by Reference lesson of the Programming Fundamentals course applies here exactly:

```js
const record = { station: "A1", temperature: 21.5 };
const alias = record;
alias.temperature = 22.75;
console.log(record.temperature);

function mutates(r) { r.temperature = 0; }
function doesNotMutate(r) { return { ...r, temperature: 0 }; }

mutates(record);
console.log(record.temperature);
console.log(doesNotMutate(record), record.temperature);
```

```
22.75
0
{ station: 'A1', temperature: 0 } 0
```

The `mutates` function changed the caller's data. `doesNotMutate` produced a new object
and left the original record as it was — the `0` in the last line is left over from the
`mutates` call.

This course's rule: **transformation functions do not change their inputs; they return
a new object.** If a side-effecting update is actually needed, the function's name
should say so.

## Applying It to the Measurement Script

Grouping records by station is the object used as a map:

```js
const records = [
  { station: "A1", temperature: 21.5 },
  { station: "A2", temperature: 19.75 },
  { station: "A1", temperature: 22.75 },
  { station: "B1", temperature: 23 },
];

const groups = {};
for (const record of records) {
  const key = record.station;
  if (!Object.hasOwn(groups, key)) {
    groups[key] = [];
  }
  groups[key].push(record.temperature);
}
console.log(groups);

const averages = Object.fromEntries(
  Object.entries(groups).map(([name, values]) => [
    name,
    values.reduce((t, v) => t + v, 0) / values.length,
  ]),
);
console.log(averages);
```

```
{ A1: [ 21.5, 22.75 ], A2: [ 19.75 ], B1: [ 23 ] }
{ A1: 22.125, A2: 19.75, B1: 23 }
```

Both steps use this lesson's tools. Grouping writes to the object with a computed key
and does the existence check with `Object.hasOwn`. The average computation converts the
object to pairs, applies a map, and converts it back to an object. The callback's
parameter was destructured with the `[name, values]` syntax.

## Summary

- Shorthand property, computed key, and shorthand method are the three shortcuts of
  object syntax.
- Keys other than symbols are converted to strings; `1` and `"1"` are the same key.
- A field being absent and carrying `undefined` are separate situations; the
  distinction is seen with `Object.hasOwn`.
- `Object.entries` and `Object.fromEntries` are each other's inverse and make it
  possible to use array methods on an object.
- Destructuring offers renaming, defaults, nested destructuring, and gathering
  remaining fields.
- In spread, a property written later overwrites the earlier same-named one; the copy
  is shallow, and objects are bound to names by reference.

## Next Step

Up to this lesson, output was produced with `console.log` arguments or concatenation.
The next lesson takes up strings: formatting with template literals, search and split
methods, the practical consequences of the code-unit/grapheme distinction, and number
formatting. The measurement report's readable text will be written there.
