Emmanuel Akinfulubi

Lesson 01 of 159 min read

What an Object Actually Is

Before classes, before inheritance, before any of the vocabulary: an object is a labelled bundle of things that belong together. That is the whole idea.

By the end: Make an object by hand and read values back out of it.

Say you are keeping records for a motor park full of buses. One of them carries the plate LAG-441-XA. It runs Lagos to Abuja, it has nine seats still unsold, and it was registered in 2019.

You could store that with four separate variables:

Four facts, four variables, no connection between them

const plate = 'LAG-441-XA';
const route = 'Lagos - Abuja';
const seatsLeft = 9;
const registeredIn = 2019;

Nothing here says these four facts describe the same bus. Add a second bus and you are inventing names like plate2 and seatsLeft2. Add forty and the whole thing collapses.

An object solves exactly this and nothing more. It is one value that holds named facts which belong together.

The same four facts, gathered

const bus = {
  plate: 'LAG-441-XA',
  route: 'Lagos - Abuja',
  seatsLeft: 9,
  registeredIn: 2019,
};

console.log(bus);

Output


      

Read that syntax slowly, because you will type it thousands of times.

The key is the label. The value is the thing. That pair together is called a property.

Getting things back out

Two ways in. Dot notation is what you will use almost always:

Dot notation, and its bracket cousin

const bus = { plate: 'LAG-441-XA', seatsLeft: 9, registeredIn: 2019 };

console.log(bus.plate);
console.log(bus.seatsLeft);

// Brackets do the same job, but the key is written as a string.
console.log(bus['registeredIn']);

// Which means brackets can take a key you worked out at runtime.
const whichOne = 'seatsLeft';
console.log(bus[whichOne]);

Output


      

Ask for a property that is not there and JavaScript does not complain. It hands you undefined.

Missing is not an error

const bus = { plate: 'LAG-441-XA', seatsLeft: 9 };

console.log(bus.owner);
console.log(typeof bus.owner);

// So a plain if-check reads well:
if (bus.owner) {
  console.log('Owner on file.');
} else {
  console.log('No owner recorded.');
}

// And `in` answers the sharper question: is the key present at all?
console.log('owner' in bus);
console.log('seatsLeft' in bus);

Output


      

Objects change

Assign to a property that exists and you replace it. Assign to one that does not and you create it.

Add, change, remove

const bus = { plate: 'LAG-441-XA', seatsLeft: 9 };

bus.seatsLeft = 10;          // changed
bus.owner = 'C. Okafor';     // created
delete bus.seatsLeft;        // gone

console.log(bus);
console.log(Object.keys(bus));
console.log(Object.values(bus));

Output


      

Objects inside objects, objects inside arrays

A value can be anything, including another object or an array. That is how you describe something with real structure.

Structure, nested

const bus = {
  plate: 'LAG-441-XA',
  body: {
    seats: 14,
    features: ['air conditioning', 'reclining seats', 'TV'],
  },
  today: {
    route: 'Lagos - Abuja',
    seatsLeft: 9,
  },
};

console.log(bus.body.seats);
console.log(bus.body.features[0]);
console.log(bus.today.seatsLeft);

Output


      

And a whole park is an array of objects. This shape, a list of records, is most of the data you will ever handle.

A list of records

const park = [
  { plate: 'LAG-441-XA', seatsLeft: 9,  ready: true },
  { plate: 'ABJ-772-KM', seatsLeft: 6,  ready: false },
  { plate: 'ENU-318-PH', seatsLeft: 11, ready: true },
];

for (const bus of park) {
  console.log(bus.plate, '-', bus.seatsLeft, 'seats left');
}

const ready = park.filter(b => b.ready);
console.log('Ready to depart:', ready.map(b => b.plate));

const total = park.reduce((sum, b) => sum + b.seatsLeft, 0);
console.log('Seats still open across the park:', total);

Output


      

The one thing that surprises everybody

An object variable does not hold the object. It holds a reference to it, like a tag pointing at something parked in the yard. Copy the variable and you copy the tag, not the bus.

Two names, one object

const original = { plate: 'LAG-441-XA', seatsLeft: 9 };
const alias = original;

alias.seatsLeft = 12;

console.log('original.seatsLeft is', original.seatsLeft);
console.log('Same object?', original === alias);

// A separate object with identical contents is still a different object.
const twin = { plate: 'LAG-441-XA', seatsLeft: 12 };
console.log('Equal contents, same object?', original === twin);

Output


      

Shallow versus deep, shown

const original = {
  plate: 'LAG-441-XA',
  body: { seats: 14 },
};

const shallow = { ...original };
shallow.plate = 'COPY-000-XX';   // own property, safe
shallow.body.seats = 99;         // shared object, not safe

console.log('after shallow edit, original seats:', original.body.seats);

const deep = structuredClone(original);
deep.body.seats = 1;
console.log('after deep edit, original seats:', original.body.seats);

Output


      

Your turn: describe something real

Replace the bus below with something from your own life: a phone, a generator, a laptop, a recipe. Give it at least four properties, one of which is an array and one of which is a nested object. Then log two things out of it. Run it as often as you like; nothing here can break.

Editable. Change it, then run it.

Output


      

Recap

  • An object gathers named facts that belong together into one value.
  • obj.key reads a property; obj['key'] does the same when the key is dynamic or awkward.
  • A missing property is undefined, not an error, and 'key' in obj asks whether it exists at all.
  • const protects the variable, never the contents.
  • Object variables hold references. Assignment shares; { ...obj } copies one level; structuredClone(obj) copies all of it.

Saved in this browser only.

Newsletter

New writing, when it lands.

Occasional notes on shipping software with AI agents. No schedule, no filler, unsubscribe in one click.