1.Arrays — ordered lists
So far we have put one value in one variable. But you cannot store 30 students' scores in 30 variables. An array is a data type that holds several values in order under one name. You make one by listing values separated by commas inside square brackets, like [70, 85, 90]. The lists we took apart one by one with for...of in Lesson 4 were arrays.
You take values out of an array by their position number, the index. Indexes start at 0, not 1, so the first value is arr[0] and the second is arr[1]. The number of values is arr.length, and the index of the last value is always arr.length - 1. This is exactly where the off-by-one mistakes from Lesson 4 come from.
Reading an index that doesn't exist gives no error, just undefined. In an array of length 3, reading arr[3] or arr[-1] both give undefined. If you want to count from the end, arr.at(-1) gives the last value. You can mix numbers, strings and booleans in one array, but in practice arrays are easier to handle when they hold values of the same kind.
undefinedconst fruits = ['apple', 'pear', 'plum'];
console.log(fruits[0], fruits[2]);
console.log(fruits.length);
console.log(fruits[fruits.length - 1]);
console.log(fruits[3]);
console.log(fruits.at(-1));apple plum 3 plum undefined plum
2.Changing and searching arrays — `push`, `pop`, `includes`, `indexOf`
push adds a value to the end of an array, and pop takes the last value out, returning it and removing it from the array. You can also change a value by assigning to an index directly, as in arr[1] = 'grape'. Here is something easy to get confused about: even an array created with const can have its contents changed. What const prevents is "putting a different array into that name," not changing the slots inside the array.
To check whether a value is in an array, includes returns true or false and indexOf returns its position. indexOf returns -1 when it finds nothing — the same convention we used in Lesson 4 to mark "not found." So if you write if (arr.indexOf(x)), it is false when the value is in the first slot (0) and true when it is not found (-1) (truthy and falsy from Lesson 3). If you only want to know whether it is there, use includes.
Putting an array into another variable does not copy it; it creates one more name that points to the same array. In the code below, a push onto b changes a too. It is like two people sharing the address of the same house. If you really need a separate copy, spread it into a new array with [...a]. Objects behave exactly the same way.
push, pop, includes, indexOfconst cart = ['milk', 'bread'];
cart.push('eggs');
console.log(cart, cart.length);
const last = cart.pop();
console.log(last, cart);
console.log(cart.includes('bread'), cart.indexOf('bread'));
console.log(cart.indexOf('rice'));[ 'milk', 'bread', 'eggs' ] 3 eggs [ 'milk', 'bread' ] true 1 -1
const a = [1, 2];
const b = a;
b.push(3);
console.log(a);
const c = [...a];
c.push(4);
console.log(a, c);[ 1, 2, 3 ] [ 1, 2, 3 ] [ 1, 2, 3, 4 ]
3.Objects — labeled slots
If arrays find values by "which position," objects find values by "which name." You make one by listing key: value pairs separated by commas inside curly braces, like { name: 'Alex', age: 20 }. Each key-value pair is called a property. Objects fit well when several pieces of information together describe one thing, such as one member or one product.
Properties are usually read with a dot, as in user.name, and when the key name is stored in a variable, with brackets, as in user[key]. Reading a property that doesn't exist gives undefined, just like a missing array slot. But if you then read a property from that undefined, you get a TypeError. The code below does exactly that; the cause is misspelling the key name as nmae. The exact wording of the message differs slightly between browsers.
This error is one of the most common ones you see when you plug AI-written code into real data. It usually happens when the key names in the data differ from the key names the code expected, or when some items are missing that property. The (reading 'length') in parentheses in the error message tells you what it failed to read, so trace back to find why the value just before it is undefined (Lesson 8).
undefinedconst user = { name: 'Alex', age: 20 };
console.log(user.name, user.age);
user.age = 21;
user.city = 'Boston';
console.log(user);
const key = 'name';
console.log(user[key]);
console.log(user.email);Alex 20
{ name: 'Alex', age: 21, city: 'Boston' }
Alex
undefinedundefined gives a TypeErrorconst user = { name: 'Alex' };
console.log(user.nmae);
console.log(user.nmae.length);undefined
TypeError: Cannot read properties of undefined (reading 'length')4.An array of objects = a table
Most real data comes in the shape of an "array of objects." Each slot of the array is a row of the table, and the object's keys are the column names. Think of it as one sheet of a spreadsheet such as Excel moved into code. The table and code below show the same fictional sales records in two ways.
In this shape, combining the loops of Lesson 4 with the property reading you just learned lets you do almost any calculation. Take out the rows one at a time (for...of), read the column you need (row.qty), and accumulate or count. In Lesson 9 you will turn a table written as text into this shape and compute totals, averages and totals per group yourself.
| (index) | `item` | `price` | `qty` |
|---|---|---|---|
| 0 | notebook | 1500 | 4 |
| 1 | pencil | 500 | 10 |
| 2 | eraser | 800 | 3 |
const sales = [
{ item: 'notebook', price: 1500, qty: 4 },
{ item: 'pencil', price: 500, qty: 10 },
{ item: 'eraser', price: 800, qty: 3 },
];
let revenue = 0;
for (const row of sales) {
revenue += row.price * row.qty;
}
console.log(revenue);13400
- Step 1, what to accumulate: the revenue total. Starting value
0. - Step 2, the work for one row: add
row.price * row.qty. Notebook 6,000, pencil 5,000, eraser 2,400. - Step 3, the result: 6,000 + 5,000 + 2,400 = 13,400 won.
- Check: there are 3 rows, so there should be 3 passes. Printing the running total for each row shows it growing 6000 → 11000 → 13400.
5.A first taste of `map`, `filter` and `reduce`
Arrays have methods that stand in for loops. The three most used are map, filter and reduce. All three take an arrow function like those in Lesson 5 and call it for each value in the array. map builds a new array from the transformed value of each item (same length), filter builds a new array of only the values for which the function returned true (same length or shorter), and reduce folds the values into one, such as a total.
The important point is that map and filter do not change the original array; they return a new one. This is the same property as the pure functions of Lesson 5, so the results are easy to predict. With reduce, always pass a starting value as the second argument. The 0 in reduce((s, x) => s + x, 0) corresponds to let sum = 0 in the running-total pattern of Lesson 4. Leave out the starting value and an empty array gives a TypeError.
At first a loop may be easier to read, and that's fine. These methods are just a shorter way to write what loops can do. However, AI-written code often chains these three together, so it is worth practicing reading such chains by breaking them into single steps and printing the intermediate results.
map transforms, filter picks, reduce folds — the original array stays the sameconst prices = [1500, 500, 800, 12000];
const withTax = prices.map((p) => p * 1.1);
console.log(withTax.map((p) => Math.round(p)));
const cheap = prices.filter((p) => p < 1000);
console.log(cheap);
const total = prices.reduce((s, p) => s + p, 0);
console.log(total);
console.log(prices);[ 1650, 550, 880, 13200 ] [ 500, 800 ] 14800 [ 1500, 500, 800, 12000 ]
| Method | What it does | What it returns | As a loop |
|---|---|---|---|
map | Transforms each value | A new array of the same length | push each transformed value into a new array |
filter | Picks values that meet a condition | A new array, same length or shorter | push only when the condition is true |
reduce | Folds into one value | A single value (a total, etc.) | The running-total pattern |
6.JSON — a text format for exchanging data
JSON is a format for writing objects and arrays as text (strings). Its name comes from JavaScript, but today almost every programming language and web service uses it to exchange data. Many configuration files, server responses and pieces of data that apps save are JSON. JSON.stringify turns a value into JSON text, and JSON.parse turns JSON text back into a value.
JSON looks like JavaScript object syntax but is stricter. Keys must be wrapped in double quotes, and strings may use only double quotes. A comma after the last item is not allowed, and comments are not allowed either. Functions and undefined cannot be stored, so when you stringify them they are dropped from object properties and turned into null inside arrays. Break even one rule and JSON.parse throws a SyntaxError.
JSON squeezed onto one long line is hard to read. Paste it into a JSON formatter tool and it will indent it for you, and it may also point out where the rules are broken. However, don't paste data containing personal information, such as real member records, into outside tools or AI; replace it with fictional data that has the same structure before checking it (Lesson 10).
const item = {
name: 'notebook',
price: 1500,
tags: ['office'],
};
const text = JSON.stringify(item);
console.log(text);
console.log(typeof text);
const back = JSON.parse(text);
console.log(back.price + 500);{"name":"notebook","price":1500,"tags":["office"]}
string
2000const bad = "{ name: 'notebook' }";
console.log(JSON.parse(bad));SyntaxError: Expected property name or '}' in JSON at position 2 (line 1 column 3)JSON.stringify(value, null, 2), and you get multi-line text indented by two spaces. The playground on this page shows multiple lines as they are, so try it when you print long data to inspect its structure.📌 Key points
- An array is an ordered list — indexes start at 0, the last is
arr.length - 1, and a missing slot isundefined - An object is a bundle where you find values by name (key) — reading a property again from
undefinedgives aTypeError - Putting an array or object into another variable does not copy it; both names point to the same thing
- An array of objects is a table — take out each row, read its columns and accumulate, or process it with
map,filterandreduce - JSON means double-quoted keys and no trailing commas —
stringifyturns values into text,parseturns text into values
🧪 Code lab
Write functions that read arrays and objects, and that accumulate and pick values from an array of objects (a table). Boundary values such as empty arrays are graded too.
Your code runs only inside an isolated sandbox in this browser and is never sent to a server. It has no network access and is stopped after 2 seconds. Edited code is saved only in this browser. Ctrl+Enter (⌘+Enter) runs it; Tab inserts two spaces (press Esc, then Tab, to move on).
JavaScript is off, so the code can't run here, but you can still read each task, its starter code, the automatic checks and a sample solution.
1Get the last value
Write a function lastItem(arr) that returns the last value of the array arr. For an empty array, return null.
lastItem([1,2,3])expected3lastItem(["apple"])expected"apple"lastItem([])expectednulllastItem([0,false])expectedfalse
💡 Hint
In an empty array, arr[arr.length - 1] is arr[-1], which is undefined. That is why the empty array is handled separately first.
Show a sample solution
function lastItem(arr) {
if (arr.length === 0) {
return null;
}
return arr[arr.length - 1];
}2Total quantity
Write a function totalQty(rows) that takes an array rows of objects shaped like { item, qty } and returns the sum of qty. For an empty array, return 0.
totalQty([{"item":"notebook","qty":4},{"item":"pencil","qty":10}])expected14totalQty([])expected0totalQty([{"item":"eraser","qty":3}])expected3totalQty([{"item":"a","qty":0},{"item":"b","qty":0}])expected0
💡 Hint
Each row is an object. Read row.qty with dot notation. You can also write it on one line with reduce.
Show a sample solution
function totalQty(rows) {
let total = 0;
for (const row of rows) {
total += row.qty;
}
return total;
}3Pick only the names that match
Write a function namesFrom(rows, min) that takes an array rows of objects shaped like { item, price } and a minimum price min, and returns an array of only the item values of rows whose price is min or more, in their original order. If no row matches, return an empty array [].
namesFrom([{"item":"notebook","price":1500},{"item":"pencil","price":500},{"item":"bag","price":20000}], 1000)expected["notebook","bag"]namesFrom([], 100)expected[]namesFrom([{"item":"pencil","price":500}], 500)expected["pencil"]namesFrom([{"item":"pencil","price":500}], 501)expected[]
💡 Hint
It takes two steps: pick the rows with filter, then pull out just the names with map. Using a loop with if and push works too.
Show a sample solution
function namesFrom(rows, min) {
return rows
.filter((r) => r.price >= min)
.map((r) => r.item);
}4Count each item
Write a function countBy(words) that takes an array of strings words and returns an object holding how many times each word appeared. Example: ['apple', 'pear', 'apple'] → { apple: 2, pear: 1 }. For an empty array, return an empty object {}.
countBy(["apple","pear","apple"])expected{"apple":2,"pear":1}countBy([])expected{}countBy(["a"])expected{"a":1}countBy(["x","x","x","y"])expected{"x":3,"y":1}
💡 Hint
The key name is in the variable w, so use brackets, counts[w], not dot notation. A word seen for the first time is undefined.
Show a sample solution
function countBy(words) {
const counts = {};
for (const w of words) {
if (counts[w] === undefined) {
counts[w] = 1;
} else {
counts[w] += 1;
}
}
return counts;
}🤖 Try asking AI like this
Copy a prompt and replace the [ ] parts with your own situation. Don't take the answer on trust — check it against this lesson.
When you're unsure how to store data in arrays and objects
Turn the following fictional data into a JavaScript "array of objects." Use lowercase English key names, and make numbers actual numbers, not strings. Then show 3 calculations you could do with this data (a total, picking rows by a condition, counting per group), with a loop version and a `map`/`filter`/`reduce` version side by side. Data: [paste a fictional table]
When code that chains `map`, `filter` and `reduce` is hard to read
Break the `map`/`filter`/`reduce` chain in the code below into single steps, and use a small example input to show what array or value each step produces. Also write a `for...of` loop version that does the same thing. Code: [paste here]
When `JSON.parse` throws an error
Find every rule violation (quotes, trailing commas, comments, etc.) that makes the following JSON string fail in `JSON.parse`. Also show the corrected JSON. The content is fictional example data: [paste here]
🧰 Related tools
Tools for checking and tidying the JSON, regular expressions and text from this lesson. Don't paste real personal data or passwords.
- JSON FormatterIt indents JSON squeezed onto one line to show its structure and finds where the quote and comma rules are broken. Try the
JSON.parseerrors from this lesson in it. - Text Diff CheckerCompare JSON before and after processing side by side to see at a glance which rows and values
mapandfilterchanged. - Word Frequency AnalyzerA tool that counts each word, so you can compare its results with the per-item counting function you build in the exercises.
- MDN Web Docs — JavaScript Guide: Indexed collections, Working with objects
- MDN Web Docs — reference for Array.prototype.map / filter / reduce and JSON.stringify / JSON.parse
- General rules of the ECMA-404 JSON data interchange syntax standard
Reached every goal above? Mark the lesson complete.
Storage is unavailable in this browser, so this lasts only for this page.💻 Coding Basics
- 1What Is a Program? — Breaking Work into Sequence, Choice, and Repetition
- 2Values, Variables, and Types — Putting Name Tags on Values
- 3Conditionals — Taking Different Paths Depending on the Situation
- 4Loops — Doing the Same Thing Many Times, Exactly
- 5Functions — Splitting Work into Small Named Machines
- 6Arrays and Objects — Storing and Handling Data
- 7Strings and Text — Cutting, Finding and Replacing Characters
- 8Debugging and Reading Errors — Turning Red Text into Clues
- 9Simple Automation — Spreadsheet Math and Text Cleanup in Code
- 10Reading and Verifying AI-Written Code — Tests, Security, Licenses, Privacy