In our Jurassic Park, dinosaur data must be strictly protected. Not every employee should have direct access to DNA sequences or enclosure security codes. Encapsulation is a fundamental principle of object-oriented programming that allows us to hide internal implementation details and expose only a controlled interface. In JavaScript, from ES2022, we have true private fields denoted by the
# symbol.Encapsulation is a principle based on hiding the internal state of an object and exposing it exclusively through defined methods. Thanks to this:
In JavaScript we declare private fields by adding
# before the field name. Such a field is accessible exclusively inside the class where it was declared:1class Dinosaur {
2 // Private fields — inaccessible from outside
3 #dnaSequence;
4 #healthStatus;
5 #dangerLevel;
6
7 // Public fields — accessible from outside
8 species;
9 name;
10
11 constructor(species, name, dnaSequence, dangerLevel) {
12 this.species = species;
13 this.name = name;
14 this.#dnaSequence = dnaSequence;
15 this.#healthStatus = 100;
16 this.#dangerLevel = dangerLevel;
17 }
18
19 // Public method — controlled access to data
20 getStatus() {
21 return `${this.name} (${this.species}): health ${this.#healthStatus}%, danger ${this.#dangerLevel}/5`;
22 }
23}
24
25const rex = new Dinosaur("Tyrannosaurus Rex", "Rexy", "ATCG-GCTA-TTAA", 5);
26
27console.log(rex.species); // "Tyrannosaurus Rex" — public field
28console.log(rex.name); // "Rexy" — public field
29console.log(rex.getStatus()); // Works — public method
30
31// console.log(rex.#dnaSequence); // SyntaxError! Private field
32// console.log(rex.#healthStatus); // SyntaxError! Private fieldAttempting to access the
#dnaSequence field from outside the class will cause a syntax error. This is true privacy — not just a convention.To allow reading or modifying private fields, we use getters (
get) and setters (set). A setter allows data validation before saving:1class DinosaurEnclosure {
2 #maxCapacity;
3 #currentDinosaurs;
4 #securityCode;
5
6 constructor(name, maxCapacity, securityCode) {
7 this.name = name;
8 this.#maxCapacity = maxCapacity;
9 this.#currentDinosaurs = [];
10 this.#securityCode = securityCode;
11 }
12
13 // Getter — read capacity
14 get capacity() {
15 return this.#maxCapacity;
16 }
17
18 // Getter — number of dinosaurs
19 get dinosaurCount() {
20 return this.#currentDinosaurs.length;
21 }
22
23 // Getter — list of names (a copy, not a reference!)
24 get dinosaurs() {
25 return [...this.#currentDinosaurs];
26 }
27
28 // Setter with validation
29 set maxCapacity(value) {
30 if (value < this.#currentDinosaurs.length) {
31 throw new Error("Cannot reduce capacity below current number of dinosaurs!");
32 }
33 if (value <= 0) {
34 throw new Error("Capacity must be greater than zero!");
35 }
36 this.#maxCapacity = value;
37 }
38
39 // Public method with validation
40 addDinosaur(dinoName) {
41 if (this.#currentDinosaurs.length >= this.#maxCapacity) {
42 return `Enclosure ${this.name} is full! Maximum capacity: ${this.#maxCapacity}`;
43 }
44 this.#currentDinosaurs.push(dinoName);
45 return `${dinoName} added to enclosure ${this.name}`;
46 }
47
48 // Method requiring authorization
49 getSecurityCode(authToken) {
50 if (authToken !== "PARK-ADMIN-2024") {
51 return "No access! Administrator authorization required.";
52 }
53 return this.#securityCode;
54 }
55}
56
57const enclosure = new DinosaurEnclosure("Raptor Pen", 4, "SEC-7742");
58
59console.log(enclosure.name); // "Raptor Pen"
60console.log(enclosure.capacity); // 4 — getter
61console.log(enclosure.addDinosaur("Blue")); // "Blue added..."
62console.log(enclosure.addDinosaur("Charlie")); // "Charlie added..."
63console.log(enclosure.dinosaurCount); // 2
64
65// Getter returns a copy — modification doesn't affect the original
66const dinos = enclosure.dinosaurs;
67dinos.push("Hacker-Dino");
68console.log(enclosure.dinosaurCount); // Still 2!
69
70// Validation in setter
71enclosure.maxCapacity = 6; // OK
72// enclosure.maxCapacity = 0; // Error! Capacity must be > 0
73
74// Access control for sensitive data
75console.log(enclosure.getSecurityCode("wrong-token")); // "No access!"
76console.log(enclosure.getSecurityCode("PARK-ADMIN-2024")); // "SEC-7742"Just like fields, methods can also be private. Private methods serve as internal helper mechanisms of the class:
1class DNAAnalyzer {
2 #samples;
3 #analysisLog;
4
5 constructor() {
6 this.#samples = [];
7 this.#analysisLog = [];
8 }
9
10 // Private method — sample validation
11 #validateSample(sample) {
12 const validBases = ["A", "T", "C", "G"];
13 return sample.split("").every(base => validBases.includes(base));
14 }
15
16 // Private method — operation logging
17 #log(message) {
18 this.#analysisLog.push({
19 timestamp: new Date().toISOString(),
20 message
21 });
22 }
23
24 // Public method using private ones
25 addSample(species, dnaSequence) {
26 if (!this.#validateSample(dnaSequence)) {
27 this.#log(`Rejected DNA sample for ${species}: invalid sequence`);
28 return "Error: Invalid DNA sequence!";
29 }
30
31 this.#samples.push({ species, dna: dnaSequence });
32 this.#log(`Added DNA sample for ${species}`);
33 return `DNA sample for ${species} registered successfully`;
34 }
35
36 // Public access to results
37 getSampleCount() {
38 return this.#samples.length;
39 }
40
41 getLog() {
42 return [...this.#analysisLog]; // Copy of the log
43 }
44}
45
46const analyzer = new DNAAnalyzer();
47console.log(analyzer.addSample("T-Rex", "ATCGATCG")); // Registered
48console.log(analyzer.addSample("Raptor", "ATCGXYZ")); // Error!
49console.log(analyzer.getSampleCount()); // 1
50console.log(analyzer.getLog()); // Operation history
51
52// analyzer.#validateSample("ATCG"); // SyntaxError! Private methodImagine that without encapsulation someone could directly modify the state of the park's security system:
1// WITHOUT encapsulation — dangerous!
2class UnsafePark {
3 fences = true;
4 electricPower = true;
5 dinosaurCount = 15;
6}
7
8const park = new UnsafePark();
9park.fences = false; // Someone turned off the fences!
10park.dinosaurCount = -5; // Nonsensical value
11// No validation, no control — catastrophe!
12
13// WITH ENCAPSULATION — safe!
14class SafePark {
15 #fencesActive;
16 #electricPower;
17 #dinosaurCount;
18
19 constructor(dinoCount) {
20 this.#fencesActive = true;
21 this.#electricPower = true;
22 this.#dinosaurCount = dinoCount;
23 }
24
25 deactivateFences(authCode) {
26 if (authCode !== "EMERGENCY-OVERRIDE") {
27 return "Denied! Disabling fences requires an emergency code.";
28 }
29 this.#fencesActive = false;
30 return "WARNING: Fences deactivated!";
31 }
32
33 get status() {
34 return {
35 fences: this.#fencesActive ? "ACTIVE" : "INACTIVE",
36 power: this.#electricPower ? "ON" : "OFF",
37 dinosaurs: this.#dinosaurCount
38 };
39 }
40}
41
42const safePark = new SafePark(15);
43console.log(safePark.deactivateFences("wrong")); // Denied!
44console.log(safePark.status); // Everything safeImportant note: private fields with
# are not accessible in child classes. If a child class needs access to the parent's data, the parent must expose it through public methods or getters:1class Animal {
2 #name;
3 #health;
4
5 constructor(name, health) {
6 this.#name = name;
7 this.#health = health;
8 }
9
10 // Getter exposes value to child classes
11 get name() {
12 return this.#name;
13 }
14
15 get health() {
16 return this.#health;
17 }
18
19 // Protected method (convention _) allowing modification of health
20 _setHealth(value) {
21 if (value < 0) value = 0;
22 if (value > 100) value = 100;
23 this.#health = value;
24 }
25}
26
27class ParkDinosaur extends Animal {
28 #species;
29
30 constructor(name, species, health) {
31 super(name, health);
32 this.#species = species;
33 }
34
35 feed() {
36 // Using public getters and parent methods
37 const newHealth = Math.min(this.health + 10, 100);
38 this._setHealth(newHealth);
39 return `${this.name} (${this.#species}) fed. Health: ${this.health}%`;
40 }
41}
42
43const dino = new ParkDinosaur("Rexy", "T-Rex", 70);
44console.log(dino.feed()); // "Rexy (T-Rex) fed. Health: 80%"Encapsulation with private fields
# is a powerful tool that allows:In Jurassic Park, encapsulation protects our systems just as fences protect visitors from dinosaurs — controlled, secure access instead of chaos.