Checkpoint: Core JavaScript
You've learned the this keyword, destructuring , spread/rest , map/filter/reduce , hoisting , scope and Map/Set — let's put them together.
Learn Checkpoint: Core JavaScript in our free JavaScript course — a beginner-friendly interactive lesson with runnable examples, a practice exercise and a…
Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
No new concepts here. Instead, you'll combine the whole core toolkit on one realistic problem, then test yourself with a short quiz. This is exactly the kind of data-shaping you do every day in real apps.
Decided by the call site. call / apply run now with a chosen this ; bind returns a function with this locked in.
Unpack arrays by position and objects by name, with renaming and defaults — even in function parameters.
The same ... spreads collections out (copy, merge, override) and gathers leftovers in (variadic params, the tail).
map changes, filter chooses, reduce fuses. Chain them into clean, loop-free data pipelines.
Declarations are prepared before code runs; let / const are block-scoped and live in the TDZ until their line.
Map for any-key/value pairs; Set for unique values and effortless deduplication.
You're given an array of user objects from an API. Your job is to produce a single summary object — the kind of thing you'd feed to a dashboard. This pulls in destructuring, filter , map , reduce , and a Set all at once.
Build a function summarize(users) that returns an object with:
Use the starter below. The expected output is shown in the comments.
Fill in the four pieces marked with ___ . Run it and check your output against the comments.
Stuck, or want to compare your approach? Reveal a clean reference solution below.
Notice how each tool does one job: filter chooses the active users, destructuring {'( )'} pulls a field cleanly, map + reduce totals the spend, and Set removes duplicate countries in a single expression.
Want more? Extend summarize to also return spendByCountry — a Map (or object) of total spend per country. Hint: reduce into an object, keying by u.country .
Answer each in your head (or out loud), then reveal to check. Six quick questions across everything you've covered.
1. What decides the value of this inside a regular function?
The call site — how the function is called, not where it's written. The object before the dot is usually this .
0 . Defaults only replace undefined ; 0 is a real value, so the default is ignored.
3. In {' '} , if both objects have a role key, which value wins?
b — the last spread wins, so b.role overwrites a.role .
4. Which method turns an array into a single value, and what must you always pass it?
reduce — and you should always pass a starting value so empty arrays don't throw and the accumulator type is clear.
5. Why does accessing a let before its declaration throw, while a var gives undefined ?
let is hoisted into the Temporal Dead Zone and is unusable until its line. var is hoisted and initialised to undefined .
6. How do you remove duplicates from [1, 1, 2, 3, 3] in one line?
[...new Set([1, 1, 2, 3, 3])] → [1, 2, 3] . A Set keeps only unique values; spread turns it back into an array.
You combined seven separate skills into one real-world data transformation and tested your recall. That blend of destructuring, the array trio, and Set is the everyday rhythm of professional JavaScript.
Up next: Callbacks & Callback Hell — your first step into asynchronous code. ⏳
Practice quiz
What decides the value of 'this' inside a regular function?
- Where the function is written
- Always the global object
- The call site — how the function is called
- The first argument passed in
Answer: The call site — how the function is called. 'this' is bound dynamically by how a function is invoked, not by where it was defined.
What does 'const { a = 5 } = { a: 0 }' set 'a' to?
- 0
- 5
- undefined
- NaN
Answer: 0. Destructuring defaults only replace undefined; 0 is a real value, so the default is ignored.
In '{ ...a, ...b }', if both objects have a 'role' key, which value wins?
- a's value
- It throws an error
- They are merged into an array
- b's value
Answer: b's value. The last spread wins, so b.role overwrites a.role.
What does [...new Set([1, 1, 2, 3, 3])] evaluate to?
A Set keeps only unique values; spreading it back into an array gives [1, 2, 3].
Calling [].reduce((s, n) => s + n) with NO initial value on an empty array does what?
- Throws a TypeError
- Returns 0
- Returns undefined
- Returns NaN
Answer: Throws a TypeError. reduce with no initial value on an empty array throws a TypeError — always pass a starting value.
Why does accessing a 'let' before its declaration line throw an error?
- let is not hoisted at all
- let is function-scoped
- It sits in the Temporal Dead Zone until its line runs
- It is initialised to null
Answer: It sits in the Temporal Dead Zone until its line runs. let and const are hoisted but stay in the Temporal Dead Zone, unusable until their declaration executes.
What does [1, 2, 3].reduce((sum, n) => sum + n, 0) return?
- 0
- 6
Answer: 6. reduce folds the array starting from 0: 0+1+2+3 = 6.
What does the array trio do, in order? map / filter / reduce.
- choose / change / fuse
- fuse / change / choose
- change / fuse / choose
- change / choose / fuse
Answer: change / choose / fuse. map changes each element, filter chooses which to keep, reduce fuses them into one value.
After 'const [first, ...rest] = [1, 2, 3, 4]', what is 'rest'?
The rest pattern gathers all remaining elements, so rest is [2, 3, 4].
Which collection is purpose-built for storing unique values and deduplicating?
- Array
- Map
- Set
- Object
Answer: Set. Set stores only unique values; Map is for any-key/value pairs.