Unit 1 · Module 3

Why JavaScript Breaks Down

What happens when small-project trust meets big-project reality

Everything we've covered in this module works. Variables hold data. Functions do work. Types categorize data. Events trigger functions. For a small project — a calculator, a quiz, a single form — JavaScript is perfectly fine on its own.

The problems start when projects get big.

Problem 1: No one enforces the rules

Remember the "29.99" + "5.00" bug that produced "29.995.00" instead of 34.99? In a small project with one developer, you might catch that. You wrote the code, you know what price is supposed to be, you'd notice the output looks wrong.

Now imagine an app with 50 files and three developers. Developer A writes a function that expects price to be a number. Developer B calls that function and passes a string because they got it from a form field — and form fields always give you strings, even when the user types digits. Developer B doesn't know Developer A expected a number. JavaScript doesn't flag it. The bug ships. Nobody catches it for two weeks.

JavaScript lets you connect pieces that don't fit, and it stays silent about it. In a small project, you can keep the whole thing in your head. In a big project, no one person knows every function's expectations. You need the language itself to catch mismatches. JavaScript won't.

Problem 2: You can't tell what shape data should be

Look at this function:

What does data need to look like?

function processLead(data) {
  sendEmail(data.email)
  assignCaseManager(data.caseType)
  logIntake(data.firstName, data.lastName)
}

What is data? What fields does it need? Does it need email? Does it need caseType? What if someone passes in an object that has emailAddress instead of email?

JavaScript won't complain. It'll just see data.email is undefined and pass undefined to sendEmail. Depending on how sendEmail is written, it might silently fail, send an email to the word "undefined," or crash with a confusing error that doesn't point to the real problem.

In a small project, you wrote processLead and the code that calls it, so you know what shape data should be. In a big project, someone calls your function six months after you wrote it. They look at processLead(data) and have to guess what data needs to look like. They either guess right or they introduce a bug.

Problem 3: Refactoring becomes terrifying

Let's say you rename caseType to practiceArea across the app because that's what the legal team actually calls it. In a small project — find and replace, done.

In a big project with 50 files? You rename it in the database. You rename it in the API. You rename it in three components. But you missed one function buried in a utility file that still says data.caseType. JavaScript doesn't care. That field is now undefined. The feature silently breaks. Maybe in a page nobody checks often. Maybe it takes a month to notice.

The root cause

All three problems have the same root cause: JavaScript doesn't check anything before it runs. It just trusts you. When a project is small enough that one person can hold it all in their head, that trust works. When a project is big enough that no one person knows every file, that trust becomes the number one source of bugs.

That's why TypeScript exists. Not because JavaScript is bad. Because JavaScript was built for a world of small scripts on simple web pages, and we're now using it to build massive applications it was never designed for. TypeScript adds the checking that JavaScript deliberately left out.

Quick reference: async and await

You saw async and await in the click lifecycle. Here's the short version for now — we'll cover these properly in a later module.

Module 3 complete

You now understand:

Next up: Module 4 — Enter TypeScript. JavaScript with a safety net.