Data with labels instead of positions
Lesson 4-2 built a shopping list with push, and covered a method that does two jobs at once: list.pop() removes the last item and returns it, so const last = list.pop() both shrinks the array and captures the value that left. Its counterpart at the other end is shift().
Arrays like that one are the right tool when every item plays the same role and the position carries the meaning. This unit covers the other shape of data, where each piece means something different and needs a name rather than a number.
Objects are JavaScript's dictionaries
Arrays handle many of the same thing, while objects handle one thing with many facts. A user has a name, an age, and a plan. A product has a title and a price. Nearly every piece of data a server will ever send you, which is the subject of lesson 5-3, arrives in this shape, so reading and writing it has to become reflex.
An array numbers its items. An object names them. It is JavaScript's version of the Python dict you used for labeled data:
const user = { name: "Ada", age: 36, premium: true };
Each name: value pair is a property. Unlike Python dicts, the keys are written without quotes, though quotes are allowed and become necessary for keys with unusual characters.
Reading has two spellings:
- Dot notation, the everyday one:
user.name - Bracket notation, for keys stored in variables or keys with odd characters:
user["age"]oruser[someKey]
Writing works the same way. Assigning to a property that does not exist yet simply creates it, and delete user.premium removes one. As with arrays, a const object can still have its contents changed, because const only locks the name.
Reading, updating, and adding properties
Four things happen here in sequence: two reads with the two different notations, an update to an existing property, and the creation of a brand new one.
const user = { name: "Ada", age: 36, premium: true }; console.log(user.name); console.log(user["age"]); user.age = 37; user.country = "UK"; console.log(user.age); console.log(user);
Output
Ada 36 37 { name: 'Ada', age: 37, premium: true, country: 'UK' }
user.name and user["age"] are equally valid ways to read a property, and here they differ only in style. The interesting pair is user.age = 37 against user.country = "UK". Both are plain assignments, and the language decides between updating and creating based on whether the property already existed. Nothing announces that a new property is being added.
Printing the whole object at the end shows the result, with country sitting at the end because properties keep the order in which they were added.
Building a book object and extending it
A small object created with two properties, read back inside a template literal, then given a third property after the fact.
const book = { title: "Dune", pages: 412 }; console.log(`${book.title} has ${book.pages} pages`); book.author = "Frank Herbert"; console.log(book.author);
Output
Dune has 412 pages
Frank HerbertShort objects like this one fit comfortably on a single line, and the pairs are separated by commas exactly as they are in the multi-line form. Inside the template literal from lesson 1-3, the placeholders hold full property lookups, since ${...} accepts any expression and book.title is one.
Adding author afterwards is nothing more than assignment. There is no separate command for growing an object, which is convenient and also a hazard: a misspelled book.pagse = 500 quietly creates a second property rather than complaining.
Reading a property whose name is in a variable
With const key = "email"; in hand, the expression that reads that property is user[key].
The two notations differ in when the name is decided. user.key looks for a property literally called key, since a dot takes the word written after it at face value, and here that property does not exist, so the result is undefined. Bracket notation evaluates whatever sits inside the brackets first, so user[key] becomes user["email"] and finds the real property.
| Notation | Property looked up | Use it for |
|---|---|---|
user.email | email | names you know while writing the code |
user[key] | whatever key holds | names decided while the program runs |
user["sign-up date"] | sign-up date | names with spaces, dashes, or digits first |
The rule in one line: dots for names you type, brackets for names your program computes.