TypeScript

What is Encapsulation in JavaScript?

Encapsulation means hiding what doesn't need to be seen. You expose a clean interface. You keep the messy internals private. When the internals change, no...

14 Oct 2023

What is Encapsulation in JavaScript?

Encapsulation means hiding what doesn't need to be seen. You expose a clean interface. You keep the messy internals private. When the internals change, nothing outside breaks.

It's the single most important factor in decomposing a system into modules.

Here are several encapsulation techniques I use regularly — whether writing new code or refactoring old code.

Encapsulate record

I favor objects over raw records for mutable data. An object can hide what's stored and expose methods for accessing it. The consumer doesn't know or care whether a value is stored directly or calculated on the fly.

This also makes renaming painless. You can rename the internal field, provide methods for both old and new names, and migrate callers gradually.

1_n8pGRKaW_ubONku96LOVPw.webp

Encapsulate collection

Encapsulating a collection variable is common. But if the getter returns the collection itself, callers can modify its contents without the owning class knowing.

Return a copy. Or return a read-only view. Never hand out a reference to your internal collection.

1_V99gAy7_RB9dk_6lLns0jw.webp

Replace primitive with object

Early in development, you represent a phone number as a string. A price as a number. That works until you need formatting, validation, or conversion logic. Then that logic gets duplicated everywhere.

Wrapping a primitive in a small object gives behavior a home. One place to format, validate, and compare.

1_rdP2RJqUoOQJvc8K3QLm2g.webp

Replace temp with query

Temporary variables capture intermediate results. They're useful, but they can also be replaced by functions. A function gives the computation a name and makes it reusable.

The trade-off: function calls have overhead. For hot loops, keep the temp. For clarity, extract the function.

1_Yw_aSQ05lNfKTPdZxntAqg.webp

Extract class

Classes grow. You add a field here, a method there. Eventually the class handles three different responsibilities and none of them cleanly.

When a class gets too big, split it. Pull a coherent subset of data and behavior into its own class.

1_ep5XRElaeHKuqm4HnHFgbg.webp

Inline class

The opposite of extract class. If a class isn't pulling its weight anymore — maybe other refactorings moved its responsibilities elsewhere — fold it into the class that uses it most.

1_R5ob4eRPGbKK7rbW7iQkwA.webp

Hide delegate

Good modular design means modules know as little about each other as possible. If object A asks object B for object C, then A is coupled to both B and C. Hide the delegate behind B's interface.

1_v6hvwC0ayKbcOpOhMeg7oA.webp

Remove middle man

The flip side of hide delegate. If every new feature requires adding another forwarding method to the wrapper, the wrapper is just noise. Let the client call the delegate directly.

1_pwKc37_FNPB74C1MxCGGIA.webp

Substitute algorithm

Sometimes refactoring piece by piece isn't enough. The whole algorithm is wrong — or just unnecessarily complex. Replace it wholesale with something simpler.

1_9U7xZkKq8qrmadjFeUrNSg.webp

The bottom line

Encapsulation isn't about classes vs. functions. It's about controlling what's visible and what's hidden. Every technique above serves the same goal: make the code easier to change later.

Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. — Martin Golding