Chapter 7 - Dictionaries and Structuring Data (JavaScript)
Here's a JavaScript-flavoured version of the same concepts, with small JS examples for each idea.
Objects (the dictionary equivalent)
JavaScript uses plain objects for key-value pairs, written with {}. Keys are strings (or Symbols), and values can be anything.
Example:
const myCat = { size: "fat", color: "gray", age: 17 };
console.log(myCat.size); // 'fat'
console.log("My cat has " + myCat.color + " fur."); // My cat has gray fur.
Numeric keys are allowed but are converted to strings:
const spam = { 12345: "Luggage Combination", 42: "The Answer" };
console.log(spam[12345]); // 'Luggage Combination'
Objects vs arrays and ordering
Arrays are ordered sequences indexed by integers; objects are key-value mappings, and key order doesn't affect deep equality (though you need a helper to compare).
Example:
const spam = ["cats", "dogs", "moose"];
const bacon = ["dogs", "moose", "cats"];
console.log(JSON.stringify(spam) === JSON.stringify(bacon)); // false
const eggs = { name: "Zophie", species: "cat", age: "8" };
const ham = { species: "cat", age: "8", name: "Zophie" };
console.log(JSON.stringify(eggs) === JSON.stringify(ham)); // false (key order differs)
// But they have the same content — use a deep-equal library for true comparison
Accessing a missing key returns undefined (no error thrown):
const spam2 = { name: "Zophie", age: 7 };
console.log(spam2.color); // undefined
Small project: birthday dictionary
You can use an object to map names to birthdays and look them up interactively.
Example (Node.js with readline):
const readline = require("readline");
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const birthdays = { Alice: "Apr 1", Bob: "Dec 12", Carol: "Mar 4" };
function ask() {
rl.question("Enter a name: (blank to quit)\n>", (name) => {
if (name === "") return rl.close();
if (name in birthdays) {
console.log(birthdays[name] + " is the birthday of " + name);
} else {
console.log("I do not have birthday information for " + name);
rl.question("What is their birthday?\n>", (bday) => {
birthdays[name] = bday;
console.log("Birthday database updated.");
ask();
});
return;
}
ask();
});
}
ask();
Object.keys(), Object.values(), Object.entries()
Object.keys(), Object.values(), and Object.entries() return arrays of keys, values, or key-value pairs, useful in loops and membership checks.
Example:
const spam = { color: "red", age: 42 };
for (const v of Object.values(spam)) {
console.log(v); // red then 42
}
for (const k of Object.keys(spam)) {
console.log(k); // color then age
}
for (const [k, v] of Object.entries(spam)) {
console.log("Key:", k, "Value:", v);
}
Converting to a real array:
Object.keys(spam); // ['color', 'age']
Checking membership:
"color" in spam; // true
Object.values(spam).includes("red"); // true
Default values (like get())
Use ?? (nullish coalescing) for defaults when a key might not exist, avoiding undefined.
Example:
const picnicItems = { apples: 5, cups: 2 };
console.log("I am bringing " + (picnicItems.cups ?? 0) + " cups.");
console.log("I am bringing " + (picnicItems.eggs ?? 0) + " eggs.");
Without ??, picnicItems.eggs would be undefined.
Setting defaults (like setdefault())
Use ??= (logical nullish assignment) to set a key only if it is missing or null/undefined.
Example:
const spam = { name: "Pooka", age: 5 };
spam.color ??= "black";
console.log(spam); // { name: 'Pooka', age: 5, color: 'black' }
spam.color ??= "white";
console.log(spam.color); // still 'black'
Character frequency counter
You can combine ??= with a loop to count occurrences of each character in a string.
Example:
const message = "It was a bright cold day in April, and the clocks were striking thirteen.";
const count = {};
for (const character of message) {
count[character] ??= 0;
count[character] = count[character] + 1;
}
console.log(count); // object mapping each char to its count
Modeling real-world things: chessboard object
You can model a chessboard with an object whose keys are squares like 'a1'–'h8' and values are two-character piece codes like 'wK', 'bQ'.
Example board fragment:
const board = {
h1: "bK",
c6: "wQ",
g2: "bB",
h5: "bQ",
e3: "wK",
};
Missing keys represent empty squares.
Chessboard: starting position and template
A constant object holds the initial piece layout, and a template string with placeholders is used to print the board.
Tiny sketch of the idea:
const STARTING_PIECES = {
a8: "bR", b8: "bN",
a1: "wR", b1: "wN",
// ... all 32 pieces
};
const WHITE_SQUARE = "||";
const BLACK_SQUARE = " ";
printChessboard(board) function
printChessboard builds a 64-element array of strings (pieces or blanks) by looping over ranks and files, then formats them into the template.
Core idea:
function printChessboard(board) {
const squares = [];
let isWhiteSquare = true;
for (const y of "87654321") {
for (const x of "abcdefgh") {
const coord = x + y;
if (coord in board) {
squares.push(board[coord]);
} else {
squares.push(isWhiteSquare ? WHITE_SQUARE : BLACK_SQUARE);
}
isWhiteSquare = !isWhiteSquare;
}
isWhiteSquare = !isWhiteSquare;
}
// Format squares into the board template string
console.log(BOARD_TEMPLATE.replace(/{(\d+)}/g, (_, i) => squares[i]));
}
Interactive chessboard commands
The main loop keeps a mainBoard object and responds to text commands (move, remove, set, reset, clear, fill, quit) by updating the object.
Examples of command handling:
let mainBoard = { ...STARTING_PIECES };
if (response[0] === "move") { // move e2 e4
mainBoard[response[2]] = mainBoard[response[1]];
delete mainBoard[response[1]];
} else if (response[0] === "remove") { // remove e2
delete mainBoard[response[1]];
} else if (response[0] === "set") { // set e2 wP
mainBoard[response[1]] = response[2];
} else if (response[0] === "reset") {
mainBoard = { ...STARTING_PIECES };
} else if (response[0] === "clear") {
mainBoard = {};
}
The spread { ...STARTING_PIECES } creates a shallow copy (like Python's copy.copy).
Nested objects and arrays
You can nest objects inside objects (and mix with arrays) to represent richer structures, like guests and the items they bring to a picnic.
Example data and function:
const allGuests = {
Alice: { apples: 5, pretzels: 12 },
Bob: { "ham sandwiches": 3, apples: 2 },
Carol: { cups: 3, "apple pies": 1 },
};
function totalBrought(guests, item) {
let numBrought = 0;
for (const [k, v] of Object.entries(guests)) {
numBrought = numBrought + (v[item] ?? 0);
}
return numBrought;
}
console.log("Apples", totalBrought(allGuests, "apples")); // 7
console.log("Cups", totalBrought(allGuests, "cups")); // 3
Overall idea of the chapter
The chapter's main message is: JavaScript objects work like Python dictionaries, letting you organize data with meaningful keys. The syntax differs (dot notation, ??, Object.keys()), but the core concept of key-value storage and nesting is the same. You can model real-world state like chessboards or inventories in a structured, scalable way.