Objects and JSON

When you program, you organize. You organize sequential data into arrays or lists. You organize related data into structs or classes. A struct is a collection of key-value pairs, and a class is a collection of key-value pairs along with methods for interacting with the values. JavaScript has one entity called object that can be used like either a struct or a class. In this book, you will only use objects in a struct-like way; they will not have any methods.

Unlike structs in C or C++, you don't declare the fields or properties of a JavaScript object ahead of time. Rather, you make objects on the fly, perhaps using this object literal syntax:

const where = {
latitude: 38.4341,
longitude: 78.8632
};
const foundings = {
Virginia: 1776
};
const phonebook2030 = {};

New key-value pairs are may be added at any time from an object:

foundings.Iowa = 1846;
foundings['New Jersey'] = 1787;

Accessing properties is done using either the . operator or the [] operator. The dot operator only works when the property name is a legal identifier. The [] operator, on the other hand, allows the property name to contain punctuation and space or to be computed.

Try executing the two code snippets above in your JavaScript console. Observe how foundings is declared const, yet the additions of Iowa and New Jersey are perfectly legal. That's because const only stops the variable itself from being bound to some other value. It doesn't stop the value itself from being modified. This is confusing, so read this paragraph again. Try assigning where to the empty object.

Try accessing the latitude of where. Try accessing a property named elevation.

No exception is thrown when you access non-existent properties. Instead, the lookup yields an undefined value. This value is interpreted as false in a boolean context, so you can use it in a conditional to write code that runs only when the property is available:

if (where.elevation) {
console.log("Your elevation:", where.elevation);
}

Try setting the elevation to 0 and running this conditional statement. What happens?

The number 0 is a false value, so no message gets printed. The empty string is also false. More things are false in JavaScript than you might expect. Probably you'd be wiser to explicitly check for a missing property using the hasOwnProperty method:

if (where.hasOwnProperty('elevation')) {
console.log("Your elevation:", where.elevation);
}

Suppose you have an object and you want to separate its fields out into separate pieces in order to keep names short. You may destructure the object using a special syntax in an assignment statement:

let card = {suit: 'hearts', rank: 7, isLucky: false};
let {suit, rank} = card; // destructure
console.log(suit, rank);

You have several options for iterating through an object. One option is to iterate through the keys:

for (let state of Object.keys(foundings)) {
console.log(state, '->', foundings[state]);
}

Try modifying this code to iterate through and log just the values. Use Object.values instead of Object.keys.

If you want both the keys and the values, you'll get slightly better performance using Object.entries, which gives you both the key and value at the same time, without any need for an additional lookup:

for (let pair of Object.entries(foundings)) {
console.log(pair[0], '->', pair[1]);
}

Try evaluating just Object.entries(foundings) and see what it returns.

To get more meaningful names for the iterator, combine Object.entries with array destructuring:

for (let [state, year] of Object.entries(foundings)) {
console.log(state, '->', year);
}

The object literal syntax was standardized as a plain-text data interchange format called JavaScript Object Notation (JSON). This is pronounced like the name Jason. To move data around between applications or computers, an object is first serialized to a string. In the browser, you use the JSON.stringify function to serialize an object:

console.log(JSON.stringify(where));
console.log(JSON.stringify(where, null, 2));

Try running these two lines. What is the significance of the 2?

To deserialize an object that has been serialized into a string, you use JSON.parse:

const json = '{"year": 1865, "month": 4, "day": 15}';
const date = JSON.parse(json);

Though the O in JSON stands for object, the JSON standard specifies that objects, arrays, numbers, booleans, strings, and null are all serializable.