Objects

Another mutable, composite data type.

Unlike arrays, whose elements are ordered and indexed with numbers, objects have “properties” which are indexed with string names.

Object syntax

Literal objects are written enclosed in curly braces: {}s.

Within the {}s are zero or more pairs of property names and values.

Each pair consists of a property name, a colon, and the value.

Pairs are separated by commas.

Example

let point = { 'x': 10, 'y': 20 }

Makes an object with two properties 'x' and 'y'.

The value of the 'x' property is 10.

The value of the 'y' property is 20.

Properties can be accessed with [] operator

» point['x']
10

» point['y']
20

Syntactic sugar

Syntactic sugar is anything in the syntax of a programming language that makes it easier or more convenient to read or write without actually enabling anything that couldn’t be done with a more verbose syntax.

Sugar for objects

When a property name follows the rules for Javascript variables we can omit the quotation marks around the property name in the object syntax:

let point = { x: 10, y: 20 };

And we can access the property with a dot followed by the property name not in quotes.

» point.x
10

» point.y
20

What are objects good for?

Objects are useful whenever we want to collect related values into a tidy package that stays together.

A scenario

We want to write a function drawConnectedPoints that draws a bunch of line segments through a series of points passed as an argument, or aguments, to the function.

How can we represent the points we want to pass to the function?

No objects, parallel lists

// xs is a list of x-coordinates;
// ys is a parallel list of y-coordinates
const drawConnectedPoints = (xs, ys) => {
  for (let i = 0; i < xs.length - 1; i++) {
    const x = xs[i];
    const y = ys[i]
    const nextX = xs[i + 1];
    const nextY = ys[i + 1];
    drawLine(x, y, nextX, nextY, 'black');
  }
};

Parallel lists are a drag because everything you do with them you have to do in parallel.

Also it’s not always obvious that those two lists are supposed to be used together.

No objects, points as lists

// points is a list of x/y coordinates represented
// as two-element lists.
const drawConnectedPoints = (points) => {
  for (let i = 0; i < points.length - 1; i++) {
    const p = points[i];
    const next = points[i + 1];
    drawLine(p[0], p[1], next[0], next[1], 'black');
  }
};

This is better than parallel lists and in this case it’s not terrible since points only have two values and by mathematical convention they’re always listed as x and then y.

But with more complicated data it can be confusing to remember which value is supposed to be at index 0 and which at 1 and beyond.

With objects

// points is a list of point objects,
// each with an x and y coordinate.
const drawConnectedPoints = (points) => {
  for (let i = 0; i < points.length - 1; i++) {
    const p = points[i];
    const next = points[i + 1];
    drawLine(p.x, p.y, next.x, next.y, 'black');
  }
};

This solves the problems of both the two earlier versions.

Even better would be if drawLine was changed to take point objects rather than loose x and y values.

Then this could look like this:

// Assume drawLine accepts point objects as arguments.
const drawConnectedPoints = (points) => {
  for (let i = 0; i < points.length - 1; i++) {
    drawLine(points[i], points[i + 1], 'black');
  }
};

Assigning to properties

Like the elements of an array, properties of objects are assignable places.

point['x'] = 200;
point.y = 300;

Assigning object values

const p1 = { x: 10, y: 20 };
const p2 = p1;

p1 and p2 are different names for the same object. If you do this:

p1.x = 100;

it changes the property on that object so p2.x is now 100 as well.

(Note also that const only applies to the variable; it doesn’t stop us from changing the objects’ properties.)

Operators equality

Object can be compared with === and !==.

But two objects with the same properties and same values are not === to each other.

p1 === { x: 100, y: 20 } ⟹ false

But because p1 and p2 are different names for the same object:

p1 === p2 ⟹ true

Objects as arguments

const p = { x: 10, y: 20 }; // Note: x starts at 10

const foo = (point) => {
  point.x = 100; // Change value of x property
  return point;
};

const p2 = foo(p)

Inside the function the argument point is just another name for the object as we assigned to p. Changing point.x changes the object we know as p.

p.x ⟹ 100
p2 === p ⟹ true

There’s more

There’s more to say about objects including how to create objects that have their own methods in addition to their own properties but we’re going to save that for next semester.