MERN code is written in the JavaScript of the last ten years, often called ES6 or ES2015+. If you learned JavaScript from older tutorials, some of the syntax will look new. Everything below appears again and again in the server and in React, so it is worth meeting it once, calmly, before the project starts.
Run the tour file after reading each section and change values to see what happens. Learning by changing working code is faster than only reading.
const and let, never var
const makes a variable that cannot be assigned again. let makes one that can. Use const by default and let only when the value must change, such as a counter. A const object can still be changed inside (you can add a property), but you cannot point the name at a different object. The old var has confusing scope rules, so modern code never uses it.
Template strings and objects
Back ticks create template strings, which can hold values: ` Applied to ${company} . Objects group related values, and **shorthand** lets you write { role } instead of { role: role }` when the variable has the same name. You will write this constantly when building API responses.
Destructuring and spread
Destructuring pulls values out of objects and arrays into variables in one line: const { role, salary: { max } } = job. In React you will write function JobCard({ job, onStatusChange }), which is destructuring of the props object right in the parameter list.
Spread (...) copies the contents of an object or array into a new one. { ...job, status: 'interview' } is a new object with all the old fields and a changed status, and the original is untouched. This matters a great deal: React state must be replaced, not edited in place, and spread is how you do it.
Arrow functions and array methods
An arrow function is a short function: (j) => j.status === 'applied'. Combined with the array methods map, filter, find and reduce, it replaces most for loops. map turns every item into something else (a list of jobs into a list of cards), filter keeps some items, find returns the first match, and reduce folds a list into one value, such as counts per status.
Optional chaining and defaults
maybe.company?.name returns undefined instead of crashing when company is missing. ?? gives a default only when the left side is null or undefined: name ?? 'unknown'. The older || replaces every falsy value, including 0 and an empty string, which is a common source of bugs, for example when a salary of 0 is replaced by a default.
Modules: import and export
Each file is a module. export makes something available to other files, and import brings it in. In Node.js, use "type": "module" in package.json (the server in this course does) and write the .js extension in relative imports: import { formatSalary } from './helpers.js'.
The tour
// Lesson 3: the modern JavaScript used in every MERN app. Run: node examples/03-javascript/es6-tour.js
// const and let (never var)
const company = 'Acme Logistics';
let attempts = 1;
attempts += 1;
// template strings
console.log(`Applied to ${company}, attempt ${attempts}`);
// objects, destructuring and shorthand
const job = { id: 7, role: 'Dispatcher', salary: { min: 18000, max: 24000 }, tags: ['night shift', 'local'] };
const { role, salary: { max }, tags: [firstTag] } = job;
console.log(role, max, firstTag);
// spread: copy and change without touching the original (React state depends on this)
const updated = { ...job, status: 'interview' };
console.log(job.status, updated.status); // undefined interview
const moreTags = [...job.tags, 'full time'];
console.log(moreTags);
// arrow functions and array methods
const jobs = [
{ id: 1, role: 'Teller', status: 'applied' },
{ id: 2, role: 'Dispatcher', status: 'interview' },
{ id: 3, role: 'Driver', status: 'applied' },
];
const applied = jobs.filter((j) => j.status === 'applied');
const roles = jobs.map((j) => j.role);
const firstInterview = jobs.find((j) => j.status === 'interview');
const counts = jobs.reduce((acc, j) => ({ ...acc, [j.status]: (acc[j.status] || 0) + 1 }), {});
console.log(applied.length, roles, firstInterview.role, counts);
// optional chaining and default values
const maybe = { company: { name: 'Northwind' } };
console.log(maybe.company?.name ?? 'unknown', maybe.owner?.name ?? 'no owner');
// ES modules: export in one file, import in another (see helpers.js)
import { formatSalary } from './helpers.js';
console.log(formatSalary(job.salary));
export const formatSalary = ({ min, max }) => `${min.toLocaleString('en-IN')} - ${max.toLocaleString('en-IN')}`;
Run it with node examples/03-javascript/es6-tour.js. Read the output next to the code. Pay attention to the line that prints undefined interview: it proves that spread made a copy, because the original job still has no status.
Your task
- Run the tour and read each printed line against the code that produced it.
- Use
filterandmaptogether to print only the roles of jobs whose status isapplied. - Use
reduceto total thesalary.maxof an array of three jobs. - Write a function
withStatus(job, status)that returns a copy of the job with a new status and never changes the original. Check that the original is unchanged.
How to check it worked
noderuns the file with no errors.- Your
withStatusreturns a new object and the original job still has its old status.
Summary
constby default,letwhen needed, nevervar.- Destructuring takes values out; spread copies values in. Together they make non-mutating updates easy.
map,filter,findandreducereplace most loops.- Use
?.and??for safe reads and honest defaults.