You have been using this syntax in passing for three lessons, always with a footnote saying "this is explained in 04-06". The moment has come. const [removed] = tasks.splice(i, 1), for (const [i, task] of backlog.entries()), pair[0] and pair[1] while walking Object.entries: all of those are the same idea, and the idea is called destructuring. It consists of unpacking an array's elements into named variables, in a single line and with no indexes. It looks like a cosmetic detail and it is not: it changes the readability of indexed loops, it lets you swap variables without a helper, it makes a function's parameters read themselves, and it is the basis of patterns you will see in React and in almost any modern code. In this lesson you will learn it in full, and you will apply it to splitting an ISO dueDate and to processing the key-value pairs of the Taller Nómada workload summary.
Contents
- What destructuring is
- The basic syntax
- Skipping elements with commas
- Default values
- The rest with
... - Swapping variables without a helper
- Destructuring in a function's parameters
- Nested arrays
- Destructuring the result of
split() - Destructuring
Object.entries() - Destructuring in
for...of - The
[error, value]pattern and its limits - Common Mistakes and Tips
- Exercises
- Conclusion
- What destructuring is
Look at these two ways of pulling an array's elements out into variables:
const entry = ['Iván', 25, 3];
// By hand, with indexes
const assigneeA = entry[0];
const hoursA = entry[1];
const tasksA = entry[2];
// With destructuring
const [assignee, hours, tasks] = entry;
console.log(assignee, hours, tasks); // Iván 25 3The second version does exactly the same thing in one line. The rule is simple:
When you put a bracketed pattern on the left-hand side of an assignment, JavaScript does not create an array: it unpacks the array on the right, element by element, into the variables you have named, by position.
That is the key point: by position, not by name. You choose the variable names freely; what rules is the order.
const [a, b, c] = ['Iván', 25, 3];
console.log(a); // 'Iván' ← the name is irrelevant, the position countsThis is the essential difference from object destructuring, which you will study in the next lesson and which works the other way round: there the name rules and the order is irrelevant.
- The basic syntax
const tags = ['carpentry', 'purchasing', 'urgent'];
// As many variables as you want, in order
const [first, second, third] = tags;
console.log(first); // 'carpentry'
// You can take fewer elements than there are: the rest is ignored
const [onlyTheFirst] = tags;
console.log(onlyTheFirst); // 'carpentry'
// If you ask for more than there are, the extras are undefined
const [x, y, z, w] = tags;
console.log(w); // undefinedIt works the same with let, with const and with already-declared variables:
let assignee;
let hours;
[assignee, hours] = ['Lucía', 14]; // no declaration
console.log(assignee, hours); // Lucía 14Careful with that last form. If the previous line does not end in a semicolon, JavaScript may read the brackets as an index access (it is one of the ASI cases you saw in 01-04). When you destructure onto existing variables, start the line with
;or make sure the previous one is closed.
And it works with any iterable, not just arrays: strings, Set, Map…
const [firstLetter, secondLetter] = 'Nómada';
console.log(firstLetter, secondLetter); // N ó
const [one, two] = new Set([10, 20, 30]);
console.log(one, two); // 10 20
- Skipping elements with commas
If you only care about certain positions, leave the gap empty with a comma:
const row = ['Iván', 'high', 'in-progress', 12, '2026-09-30'];
// I want the assignee and the hours: I skip three positions
const [person, , , estimatedHours] = row;
console.log(person, estimatedHours); // Iván 12
// Only the status (third position)
const [, , status] = row;
console.log(status); // 'in-progress'Count the commas carefully: [, , status] has two commas before the name, so status picks up the third position. It is a compact syntax but easy to miscount; if you need to skip more than two positions, it is usually more readable to access by index or to rethink the data as an object.
- Default values
When a position does not exist (or is undefined), you can give a default value with =, exactly as in a function's parameters (03-03):
const [title, assignee = 'unassigned', reviewer = null] = ['Service the paper guillotine'];
console.log(title); // 'Service the paper guillotine'
console.log(assignee); // 'unassigned' ← position 1 did not exist
console.log(reviewer); // nullThe critical detail, the same as with default parameters: the default value only applies with undefined, not with null, nor with 0, nor with ''.
const [a = 'default'] = [null];
console.log(a); // null ← null does NOT trigger the default
const [b = 'default'] = [undefined];
console.log(b); // 'default'
const [c = 10] = [0];
console.log(c); // 0 ← 0 does not trigger it eitherIt is the same distinction that separates ?? from || (01-06), and for the same reason. If you need null to trigger the default too, destructure first and apply ?? afterwards.
Default values can be expressions, and they are only evaluated if they are needed:
function todaysDate() {
console.log(' (computing the date...)');
return '2026-09-20';
}
const [title1, date1 = todaysDate()] = ['Task A', '2026-10-01'];
// prints nothing: position 1 existed
const [title2, date2 = todaysDate()] = ['Task B'];
// (computing the date...)
console.log(date2); // '2026-09-20'
- The rest with
...
...The rest element collects everything left unassigned into a new array:
const queue = ['Signage', 'T-shirts', 'Tote bags', 'Reprint'];
const [next, ...waiting] = queue;
console.log(next); // 'Signage'
console.log(waiting); // [ 'T-shirts', 'Tote bags', 'Reprint' ]
// It also works for separating head from body
const [first, second, ...rest] = queue;
console.log(rest); // [ 'Tote bags', 'Reprint' ]Three rules of the rest element:
- It must come last.
const [...all, last] = queue;is aSyntaxError. - It always produces an array, even if nothing is left: then it will be
[], neverundefined. - It takes no default value:
[...rest = []]is not valid.
And a very useful application, copying without the first element, which is what a queue does:
function serve(queue) {
const [served, ...pending] = queue;
return { served, pending }; // it does not mutate the original queue
}
const result = serve(queue);
console.log(result.served); // 'Signage'
console.log(result.pending.length); // 3
console.log(queue.length); // 4 ✓ untouchedCompare it with queue.shift(), which does the same thing but by mutating the array (04-03). This version is immutable, which is the project's design line.
- Swapping variables without a helper
Destructuring's most celebrated trick. You used to need a temporary variable:
let a = 'Iván';
let b = 'Marta';
// The old way
let temp = a;
a = b;
b = temp;
// With destructuring: one line, no helper
[a, b] = [b, a];
console.log(a, b); // Iván Marta (back where they started)It works because the right-hand side is evaluated in full before assigning: the array ['Marta', 'Iván'] is built and only then is it distributed. It also works on an array's elements:
const order = ['T1', 'T2', 'T3'];
[order[0], order[2]] = [order[2], order[0]];
console.log(order); // [ 'T3', 'T2', 'T1' ]And for rotating three or more values at once:
- Destructuring in a function's parameters
If a function receives an array, you can unpack it in the signature itself. The parameter stops being called "that array" and starts naming its parts:
// Without destructuring: you have to remember what each index means
function describeRowA(row) {
return `${row[0]}: ${row[1]} h`;
}
// Destructuring in the signature: it reads itself
function describeRow([person, hours]) {
return `${person}: ${hours} h`;
}
console.log(describeRow(['Iván', 25])); // 'Iván: 25 h'It accepts default values and a rest element, just as outside:
function summarizeQueue([next = 'nothing', ...rest] = []) {
return `Next: ${next}. Waiting: ${rest.length}`;
}
console.log(summarizeQueue(['Signage', 'T-shirts'])); // 'Next: Signage. Waiting: 1'
console.log(summarizeQueue([])); // 'Next: nothing. Waiting: 0'
console.log(summarizeQueue()); // 'Next: nothing. Waiting: 0'That trailing = [] matters: without it, calling summarizeQueue() with no arguments would throw a TypeError, because undefined cannot be destructured. It is the same protection you will see in 04-07 with the = {} trick.
Where it shows most is in the callbacks of the methods you studied in 04-05:
const workload = { 'Iván': 25, 'Marta': 6, 'Lucía': 14 };
// Without destructuring: pair[0] and pair[1] say nothing
Object.entries(workload).forEach((pair) => console.log(`${pair[0]}: ${pair[1]} h`));
// Destructuring in the callback's parameter: readable
Object.entries(workload).forEach(([person, hours]) => console.log(`${person}: ${hours} h`));
// Iván: 25 h
// Marta: 6 h
// Lucía: 14 h
- Nested arrays
The pattern on the left can reproduce any structure, as deep as you need:
const week = [
['Monday', [8, 6]],
['Tuesday', [7, 5]]
];
const [[day, [morning, afternoon]]] = week;
console.log(day, morning, afternoon); // Monday 8 6Read it from the outside in: the outer [[...]] says "take the first element of week"; inside, [day, [morning, afternoon]] says "that element is an array of two: the first is called day, and the second is itself an array of two, morning and afternoon".
It is powerful, but it becomes unreadable very quickly. Practical rule: more than two levels of nesting and the data should probably be an object. Compare:
// Hard to read
const [[, [morningHours]]] = week;
// The same data modeled as an object: no need to count brackets
const weekObj = [{ day: 'Monday', morning: 8, afternoon: 6 }];
console.log(weekObj[0].morning); // 8
- Destructuring the result of
split()
split()Here comes the direct application to the project. split(separator) breaks a string into an array, and that array is a perfect candidate for destructuring. The canonical case: splitting an ISO dueDate.
const dueDate = '2026-09-30';
const [year, month, day] = dueDate.split('-');
console.log(year, month, day); // 2026 09 30
console.log(typeof year); // 'string' ← split always returns stringsConverting to numbers on the fly with map (04-04):
const [y, m, d] = dueDate.split('-').map(Number);
console.log(y, m, d); // 2026 9 30
console.log(typeof y); // 'number'With this you can now write a presentation function Marta has been asking for since Module 1: showing the date in a readable format.
const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'];
function readableDate(iso) {
const [year, month, day] = iso.split('-');
return `${Number(day)} ${MONTHS[Number(month) - 1]} ${year}`;
}
console.log(readableDate('2026-09-30')); // '30 September 2026'
console.log(readableDate('2026-09-05')); // '5 September 2026'
console.log(readableDate('2026-11-05')); // '5 November 2026'Notice MONTHS[Number(month) - 1]: the -1 is because months run from 1 to 12 and array indexes from 0 to 11. It is the classic off-by-one, and here it is isolated in a single easy-to-review line.
Another frequent use, splitting a line of text into fields:
const line = 'Iván;high;12;2026-09-30';
const [assignee, priority, hours, date] = line.split(';');
console.log(`${assignee} has ${hours} h at ${priority} priority`);
// Iván has 12 h at high priorityA warning: if the string does not have all the expected separators, the leftover variables end up undefined with no error at all. When you process data coming from outside, combine destructuring with default values and a validation.
const [r = 'unknown', p = 'medium', h = '0'] = 'Lucía'.split(';');
console.log(r, p, h); // Lucía medium 0
- Destructuring
Object.entries()
Object.entries()Object.entries (04-01) returns an array of [key, value] pairs. Destructuring them is what turns a cryptic walk into a readable one.
const workload = { 'Iván': 25, 'Marta': 6, 'Lucía': 14 };
// Without destructuring
for (const pair of Object.entries(workload)) {
console.log(`${pair[0]} is carrying ${pair[1]} h`);
}
// Destructuring: names instead of indexes
for (const [person, hours] of Object.entries(workload)) {
console.log(`${person} is carrying ${hours} h`);
}
// Iván is carrying 25 h
// Marta is carrying 6 h
// Lucía is carrying 14 hCombined with the methods from 04-05, the result is directly the "workload per person" block of the weekly report:
Object.entries(workload)
.toSorted(([, hoursA], [, hoursB]) => hoursB - hoursA) // destructuring and skipping the key
.forEach(([person, hours], i) => console.log(`${i + 1}. ${person}: ${hours} h`));
// 1. Iván: 25 h
// 2. Lucía: 14 h
// 3. Marta: 6 hThe comparator is worth dwelling on: ([, hoursA], [, hoursB]) => hoursB - hoursA. Both parameters are pairs, and in each one we skip the key with a comma so as to keep only the value. Compared with (a, b) => b[1] - a[1], the destructured version says what is being compared, not which position it sits in.
The way back exists too: Object.fromEntries rebuilds an object from pairs.
const workloadInWorkdays = Object.fromEntries(
Object.entries(workload).map(([person, hours]) => [person, Number((hours / 8).toFixed(1))])
);
console.log(workloadInWorkdays); // { Iván: 3.1, Marta: 0.8, Lucía: 1.8 }
- Destructuring in
for...of
for...ofYou have already seen it in lesson 04-04 with a footnote. Now you understand exactly what happens:
for (const [index, task] of backlog.entries()) {
console.log(`${index + 1}. ${task.title}`);
}
// 1. Redesign the multipurpose room
// 2. Signage for the screen-printing workshop
// ...backlog.entries() produces, on each pass, a two-element array: [0, {task 1}], [1, {task 2}]… The pattern const [index, task] unpacks that pair on the spot. And since it is still a for...of, it keeps break and continue, which was the reason for preferring it over forEach:
for (const [i, task] of backlog.entries()) {
if (task.status === 'done') continue;
if (i >= 3) break;
console.log(`${i}: ${task.title}`);
}It also works when walking arrays of arrays directly:
const assignments = [['Iván', 12], ['Marta', 6], ['Lucía', 14]];
for (const [person, hours] of assignments) {
console.log(`${person} → ${hours} h`);
}And with Map, which produces pairs naturally (04-05):
const counts = new Map([['Iván', 3], ['Marta', 2], ['Lucía', 1]]);
for (const [person, tasks] of counts) {
console.log(`${person}: ${tasks} task(s)`);
}
- The
[error, value] pattern and its limits
[error, value] pattern and its limitsIn 03-03 you studied how to return several values from a function. One of the options was returning an array, and destructuring now makes that option comfortable: the [error, value] pattern, popular in many libraries.
/**
* Validates a task. Returns [error, task]:
* if all is well, error is null; if it goes wrong, task is null.
*/
function validateTask(task) {
if (typeof task.title !== 'string' || task.title.trim() === '') {
return ['The title is required.', null];
}
if (!(task.estimatedHours > 0 && task.estimatedHours <= 40)) {
return ['Hours must be between 0 and 40.', null]; // R3
}
return [null, task];
}
const [error, validTask] = validateTask({ title: 'Service the paper guillotine', estimatedHours: 2 });
if (error) {
console.log(`✗ ${error}`);
} else {
console.log(`✓ ${validTask.title}`);
}
// ✓ Service the paper guillotine
const [error2] = validateTask({ title: '', estimatedHours: 2 });
console.log(error2); // 'The title is required.'Its virtue is that the caller chooses the names, which avoids collisions when you make several calls in a row:
Now the limits, because it is worth knowing when not to use it:
Returning an array [error, value] |
Returning an object { error, value } |
|
|---|---|---|
| Names | Set by the caller | Set by the function (they can be renamed, 04-07) |
| Order | Significant: getting it wrong is a silent bug | Irrelevant |
| Taking only the second one | const [, value] = ... (awkward comma) |
const { value } = ... |
| Adding a third piece of data | Breaks anyone who was counting positions | Breaks nothing |
| Self-documentation | Low: you have to read the function | High |
The silent bug in the second row is real and very easy to commit:
const [task, error] = validateTask({ title: 'Something', estimatedHours: 2 });
// ✗ They are the wrong way round: task is null and error holds the task object.
// There is no warning at all. The program simply does the opposite of what you think.Practical rule: use the two-element array when the two values are inseparable and obvious (a result and its error, a coordinate, a key-value pair), and whenever the caller will want to give them names of their own. For three or more pieces of data, or when the names matter, return an object, as summarizeWorkload() did in 03-03. It is the same recommendation as in that lesson, now with both syntaxes in hand for comparison.
Common Mistakes and Tips
1. Confusing position with name. In arrays the order rules. const [title, id] = [1, 'Redesign…'] assigns title = 1. With objects (04-07) the name rules.
2. Destructuring undefined or null.
const [a] = undefined; // ✗ TypeError: undefined is not iterable
const [b] = null; // ✗ TypeError
const [c] = []; // ✓ c is undefined, no errorProtect yourself with = [] in the parameters or with ?? [] on the value.
3. Miscounting the commas when skipping elements. [, , status] takes the third position. When in doubt, count the commas: there are as many skipped positions as commas before the name.
4. Putting the rest in the middle. const [...all, last] = a; is a SyntaxError. The rest always comes last.
5. Expecting the default value to apply with null. It only applies with undefined. If null must trigger the default too, apply ?? afterwards.
6. Forgetting the semicolon on the previous line when destructuring onto already-declared variables: [a, b] = [b, a] can join the line above and produce a confusing error.
7. Destructuring a Set expecting a particular order. It works because it is iterable, but the order is insertion order; do not use it to "take the two smallest".
Professional tip. Destructure when it improves reading, not for sport. const [a, , , , , f] = row; is no better than row[5]. The sign that you are forcing it is having to count commas: if your data needs names, it should probably be an object, and the next lesson will give you the exact syntax for unpacking one.
Exercises
Exercise 1 — The date, in parts. Write a function breakDownDate(iso) that takes a dueDate in the format 'yyyy-mm-dd' and returns an object { year, month, day, readable }, where year, month and day are numbers and readable has the format '30 September 2026'. Then write sameMonth(isoA, isoB), returning true if two dates fall in the same year and month. Try them with '2026-09-30', '2026-09-05' and '2026-11-05'.
Exercise 2 — Workload podium. Starting from the object const workload = { 'Iván': 25, 'Marta': 6, 'Lucía': 14 };, write podium(workload) returning an object { first, second, rest }, where first and second are strings in the format 'Iván (25 h)' and rest is an array with the same format for the others. Use Object.entries, toSorted with destructuring in the comparator, and destructuring with a rest element.
Exercise 3 — The screen-printing workshop queue, immutably. Write three functions that do not mutate the input array:
serveNext(queue)→ returns[served, remainingQueue].moveToFront(queue, position)→ returns a new queue with the order at that position placed first.swap(queue, i, j)→ returns a new queue with two positions swapped, using destructuring.
Try them with ['Signage', 'T-shirts', 'Tote bags', 'Reprint'].
Solutions
Exercise 1
const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'];
function breakDownDate(iso) {
const [year, month, day] = iso.split('-').map(Number);
return { year, month, day, readable: `${day} ${MONTHS[month - 1]} ${year}` };
}
function sameMonth(isoA, isoB) {
const [yearA, monthA] = isoA.split('-');
const [yearB, monthB] = isoB.split('-');
return yearA === yearB && monthA === monthB;
}
console.log(breakDownDate('2026-09-30'));
// { year: 2026, month: 9, day: 30, readable: '30 September 2026' }
console.log(breakDownDate('2026-09-05').readable); // '5 September 2026'
console.log(sameMonth('2026-09-30', '2026-09-05')); // true
console.log(sameMonth('2026-09-30', '2026-11-05')); // falseTwo observations. In breakDownDate, the .map(Number) converts all three parts at once, and that is what makes day come out as 5 instead of '05' —exactly what we want for the readable text. In sameMonth, by contrast, we do not convert: comparing the strings '09' with '09' works perfectly and saves the conversion. Notice too the { year, month, day, ... }: writing year instead of year: year is the property shorthand, which the next lesson will explain along with the rest of the object syntax.
Exercise 2
function podium(workload) {
const [first, second, ...rest] = Object.entries(workload)
.toSorted(([, hoursA], [, hoursB]) => hoursB - hoursA)
.map(([person, hours]) => `${person} (${hours} h)`);
return { first, second, rest };
}
console.log(podium({ 'Iván': 25, 'Marta': 6, 'Lucía': 14 }));
// { first: 'Iván (25 h)', second: 'Lucía (14 h)', rest: [ 'Marta (6 h)' ] }
console.log(podium({ 'Iván': 25 }));
// { first: 'Iván (25 h)', second: undefined, rest: [] }The chain does three things linked together from 04-05 —convert to pairs, sort and turn into text— and the destructuring on the first line distributes the result in a single gesture. The second console.log shows the behavior in the edge case: second ends up undefined and rest ends up [] (never undefined), exactly as the rule in section 5 said. If you wanted text instead of undefined, const [first, second = '—', ...rest] would be enough.
Exercise 3
function serveNext(queue) {
const [served, ...remainingQueue] = queue;
return [served, remainingQueue];
}
function moveToFront(queue, position) {
if (position < 0 || position >= queue.length) return queue.slice();
const copy = queue.slice();
const [chosen] = copy.splice(position, 1);
copy.unshift(chosen);
return copy;
}
function swap(queue, i, j) {
const copy = queue.slice();
[copy[i], copy[j]] = [copy[j], copy[i]];
return copy;
}
const queue = ['Signage', 'T-shirts', 'Tote bags', 'Reprint'];
const [served, remaining] = serveNext(queue);
console.log(served); // 'Signage'
console.log(remaining); // [ 'T-shirts', 'Tote bags', 'Reprint' ]
console.log(moveToFront(queue, 3));
// [ 'Reprint', 'Signage', 'T-shirts', 'Tote bags' ]
console.log(swap(queue, 0, 3));
// [ 'Reprint', 'T-shirts', 'Tote bags', 'Signage' ]
console.log(queue);
// [ 'Signage', 'T-shirts', 'Tote bags', 'Reprint' ] ✓ untouched in all threeAll three respect the project's rule: copy before modifying. serveNext does not even need to copy, because the rest element already creates a new array. moveToFront combines slice (copy), splice with destructuring (take it out and keep what was taken) and unshift (put it at the front), all three from 04-03. And swap is the trick from section 6 applied to an array's positions; without destructuring it would need a temporary variable.
Conclusion
Array destructuring is a small piece of syntax with a big impact on readability. You know that it unpacks by position, that you can skip elements with commas, give default values that only trigger with undefined, and collect the tail with the rest element ..., which always comes last and always produces an array. You know how to swap variables without a helper, how to destructure directly in a function's parameters —including the = [] that avoids the error when calling with no arguments— and how to unpack nested structures, with the warning that beyond two levels the data was probably asking to be an object.
And you have applied it where it really shows: splitting an ISO dueDate with split('-') to build readableDate('2026-09-30') → '30 September 2026'; walking the workload-per-assignee summary with for (const [person, hours] of Object.entries(workload)); writing comparators that say what they compare, ([, hoursA], [, hoursB]) => hoursB - hoursA; and understanding at last, without a footnote, what for (const [i, task] of backlog.entries()) means. You have also seen the [error, value] pattern and, above all, its limits against returning an object: the order is significant, getting it wrong gives no warning at all, and adding a third piece of data breaks anyone who was counting positions.
That limit is precisely the doorway into the next lesson. Nómada Tasks data does not come in pairs or triples: it comes as tasks with nine named fields, and unpacking those by position makes no sense at all. In Object Destructuring, Spread and Rest you will learn the variant that goes by name, with renaming and default values, you will finally write the 03-03 options object straight into a function's signature, and you will discover the ... operator in its other role —spread— which lets you copy and combine objects and, with that, write the immutable update { ...task, status: 'done' } that underpins all state work in modern frameworks.
JavaScript Course: From Beginner to Advanced
Module 1: Introduction to JavaScript
- What Is JavaScript?
- Setting Up Your Development Environment
- Your First JavaScript Program
- JavaScript Syntax and Basic Concepts
- Variables and Data Types
- Basic Operators
- Type Conversion and Comparisons
- The Course Project: Nómada Tasks
Module 2: Control Structures
- Conditional Statements
- Loops: for, while, do-while
- Switch Statements
- Flow Control: break, continue and Nested Loops
- Error Handling with try-catch
Module 3: Functions
- Defining and Calling Functions
- Function Expressions and Arrow Functions
- Parameters and Return Values
- Scope and Closures
- Hoisting and the Execution Context
- Higher-Order Functions
- Recursion
Module 4: Objects and Arrays
- Introduction to Objects
- Object Methods and the
thisKeyword - Arrays: Basics and Methods
- Iterating over Arrays
- Searching, Sorting and Aggregating Data: find, sort and reduce
- Array Destructuring
- Object Destructuring, Spread and Rest
- JSON and Copying Objects
Module 5: Advanced Objects and Functions
- Prototypes and Inheritance
- Classes and Object-Oriented Programming
- Encapsulation: Getters, Setters and Private Fields
- Modules: Import and Export
- Asynchronous JavaScript: Callbacks
- Promises and Async/Await
- The Event Loop and the Microtask Queue
- Iterators and Generators
Module 6: The Document Object Model (DOM)
- Introduction to the DOM
- Selecting and Manipulating DOM Elements
- Handling Events
- Propagation, Delegation and Custom Events
- Creating and Removing DOM Elements
- Rendering Lists and HTML Templates
- Handling and Validating Forms
Module 7: Browser APIs and Advanced Topics
- Local and Session Storage
- The Fetch API and AJAX
- Robust Requests: Errors, Timeouts and AbortController
- WebSockets
- Service Workers and Progressive Web Apps (PWAs)
- Essential Browser APIs
- Introduction to WebAssembly
Module 8: Testing and Debugging
- Debugging JavaScript
- Code Quality: ESLint, Prettier and Conventions
- Unit Testing with Jest
- Test Doubles: Mocks, Stubs and Spies
- Integration Testing
- End-to-End Testing with Cypress
Module 9: Performance and Optimization
- Measure Before You Optimize: DevTools and Web Vitals
- Optimizing JavaScript Performance
- Memory Management
- Efficient DOM Manipulation
- Lazy Loading and Code Splitting
Module 10: JavaScript Frameworks and Libraries
- Why Frameworks Exist
- Introduction to React
- State Management with Redux
- Vue.js Basics
- Angular Basics
- Choosing the Right Framework
