JavaScript and TypeScript course Β· Module 2: Functions, Arrays and Objects
Creating Objects (Literals, Constructors)
In this lesson8
In Jurassic Park we use JavaScript objects to represent many elements of our ecosystem - from dinosaurs and their behavior, through the areas of the park, to staff data and safety procedures. Objects are a fundamental data type in JavaScript that lets us build complex data structures with properties and methods.
Object Literals
The simplest way to create objects in JavaScript is to use an object literal - the curly brace notation {}.
1// A simple dinosaur object created with an object literal
2const velociraptor = {
3 name: "Blue",
4 species: "Velociraptor",
5 age: 4,
6 length: 2.1, // meters
7 weight: 80, // kilograms
8 maxSpeed: 64, // km/h
9 diet: "carnivore",
10 location: "Sector B",
11 dangerous: true
12};
13
14console.log(velociraptor.name); // "Blue"
15console.log(velociraptor.species); // "Velociraptor"
16console.log(velociraptor.maxSpeed); // 64Accessing Properties
We can access an object's properties in two ways:
1// Dot notation
2console.log(velociraptor.diet); // "carnivore"
3
4// Bracket notation (useful when the property name is stored in a variable)
5const propertyName = "location";
6console.log(velociraptor[propertyName]); // "Sector B"
7
8// Bracket notation is also useful when the property name contains special characters or spaces
9const dinoDetails = {
10 "full name": "Velociraptor antirrhopus",
11 "security-level": "Alpha"
12};
13
14console.log(dinoDetails["full name"]); // "Velociraptor antirrhopus"
15console.log(dinoDetails["security-level"]); // "Alpha"Object Methods
Objects can also contain functions, which we call methods:
1const velociraptor = {
2 name: "Blue",
3 species: "Velociraptor",
4 age: 4,
5 hunger: 50, // percent (0-100)
6 health: 100, // percent (0-100)
7
8 // Method for feeding the dinosaur
9 feed: function() {
10 if (this.hunger <= 0) {
11 return "Blue is not hungry.";
12 }
13
14 this.hunger -= 30;
15 if (this.hunger < 0) this.hunger = 0;
16
17 return "Blue has been fed. Hunger level: " + this.hunger + "%";
18 },
19
20 // Shorter method syntax (introduced in ES6)
21 makeSound() {
22 return "Blue makes a sharp, piercing sound!";
23 },
24
25 // Method that checks the health status
26 checkStatus() {
27 return `Dinosaur: ${this.name} (Species: ${this.species})
28Health status: ${this.health}%
29Hunger level: ${this.hunger}%
30Overall condition: ${this.health > 80 ? "Excellent" : this.health > 50 ? "Good" : "Needs veterinary care"}`;
31 }
32};
33
34console.log(velociraptor.makeSound()); // "Blue makes a sharp, piercing sound!"
35console.log(velociraptor.feed()); // "Blue has been fed. Hunger level: 20%"
36console.log(velociraptor.checkStatus());The this keyword in methods refers to the object on which the method is called.
Adding and Removing Properties Dynamically
We can dynamically add and remove properties of JavaScript objects:
1const triceratops = {
2 name: "Trixie",
3 species: "Triceratops",
4 age: 6
5};
6
7// Adding new properties
8triceratops.health = 95;
9triceratops["location"] = "Sector C";
10
11// Adding a method
12triceratops.updateHealth = function(amount) {
13 this.health += amount;
14 if (this.health > 100) this.health = 100;
15 if (this.health < 0) this.health = 0;
16 return `${this.name}'s health updated to ${this.health}%`;
17};
18
19console.log(triceratops.updateHealth(-15)); // "Trixie's health updated to 80%"
20
21// Removing a property
22delete triceratops.age;
23console.log(triceratops.age); // undefinedConstructors and the new Operator
When we need to create many similar objects, a more efficient approach is to use a constructor function and the new operator.
1// Constructor function for dinosaurs
2function Dinosaur(name, species, age, diet) {
3 this.name = name;
4 this.species = species;
5 this.age = age;
6 this.diet = diet;
7 this.health = 100;
8 this.hunger = 50;
9
10 // Method shared by all dinosaurs
11 this.feed = function() {
12 this.hunger -= 30;
13 if (this.hunger < 0) this.hunger = 0;
14 return `${this.name} has been fed. Hunger level: ${this.hunger}%`;
15 };
16}
17
18// Creating new dinosaur instances
19const blue = new Dinosaur("Blue", "Velociraptor", 4, "carnivore");
20const trixie = new Dinosaur("Trixie", "Triceratops", 6, "herbivore");
21const rex = new Dinosaur("Rex", "Tyrannosaurus", 8, "carnivore");
22
23console.log(blue.species); // "Velociraptor"
24console.log(trixie.diet); // "herbivore"
25console.log(rex.feed()); // "Rex has been fed. Hunger level: 20%"The constructor function creates a "template" for objects, and the new operator creates a new object instance based on that template.
Advantages of Constructors:
- Consistency - all objects have the same set of properties and methods
- Scalability - it is easier to create many similar objects
- Readability - the code becomes more predictable and easier to maintain
Checking an Object's Type - the instanceof Operator
We can check whether an object was created with a particular constructor:
1console.log(blue instanceof Dinosaur); // true
2console.log(velociraptor instanceof Dinosaur); // false (it was created as a literal)Classes (ES6+)
Newer versions of JavaScript (ES6+) introduced classes, which provide a friendlier syntax for object-oriented programming. Under the hood they are still constructor functions, just with a more readable syntax.
1class Dinosaur {
2 constructor(name, species, age, diet) {
3 this.name = name;
4 this.species = species;
5 this.age = age;
6 this.diet = diet;
7 this.health = 100;
8 this.hunger = 50;
9 this.isAsleep = false;
10 }
11
12 // Methods are automatically added to the prototype
13 feed() {
14 if (this.isAsleep) {
15 return `${this.name} is asleep. Better not to wake him/her for feeding.`;
16 }
17
18 this.hunger -= 30;
19 if (this.hunger < 0) this.hunger = 0;
20 return `${this.name} has been fed. Hunger level: ${this.hunger}%`;
21 }
22
23 sleep() {
24 this.isAsleep = true;
25 return `${this.name} falls asleep.`;
26 }
27
28 wakeUp() {
29 this.isAsleep = false;
30 return `${this.name} wakes up.`;
31 }
32
33 getStatus() {
34 return `
35Dinosaur: ${this.name} (Species: ${this.species})
36Age: ${this.age} years
37Diet: ${this.diet === "carnivore" ? "Carnivorous" : "Herbivorous"}
38Health status: ${this.health}%
39Hunger level: ${this.hunger}%
40State: ${this.isAsleep ? "Asleep" : "Active"}`;
41 }
42}
43
44// Creating an instance of the class
45const blue = new Dinosaur("Blue", "Velociraptor", 4, "carnivore");
46console.log(blue.getStatus());
47
48console.log(blue.sleep()); // "Blue falls asleep."
49console.log(blue.feed()); // "Blue is asleep. Better not to wake him/her for feeding."
50console.log(blue.wakeUp()); // "Blue wakes up."
51console.log(blue.feed()); // "Blue has been fed. Hunger level: 20%"Inheritance with Classes
Classes make it easy to implement inheritance:
1// Base class
2class Animal {
3 constructor(name, species) {
4 this.name = name;
5 this.species = species;
6 this.alive = true;
7 }
8
9 makeSound() {
10 return "The animal makes a sound";
11 }
12}
13
14// Derived class inheriting from Animal
15class Dinosaur extends Animal {
16 constructor(name, species, diet) {
17 // We call the base class constructor
18 super(name, species);
19 this.diet = diet;
20 this.health = 100;
21 }
22
23 // We override the method from the base class
24 makeSound() {
25 if (this.diet === "carnivore") {
26 return "ROAR!!! A terrifying roar!";
27 } else {
28 return "A gentle, low rumble.";
29 }
30 }
31
32 // We add new methods
33 eat(food) {
34 if (this.diet === "carnivore" && food.type === "meat") {
35 return `${this.name} eats ${food.name} with relish!`;
36 } else if (this.diet === "herbivore" && food.type === "plant") {
37 return `${this.name} happily nibbles on ${food.name}.`;
38 } else {
39 return `${this.name} is not interested in eating ${food.name}.`;
40 }
41 }
42}
43
44// Objects representing food
45const meat = { name: "meat", type: "meat" };
46const plants = { name: "plants", type: "plant" };
47
48// We create dinosaur instances
49const rex = new Dinosaur("Rex", "Tyrannosaurus", "carnivore");
50const spike = new Dinosaur("Spike", "Stegosaurus", "herbivore");
51
52console.log(rex.makeSound()); // "ROAR!!! A terrifying roar!"
53console.log(spike.makeSound()); // "A gentle, low rumble."
54
55console.log(rex.eat(meat)); // "Rex eats meat with relish!"
56console.log(rex.eat(plants)); // "Rex is not interested in eating plants."
57console.log(spike.eat(plants)); // "Spike happily nibbles on plants."Static Methods
Static methods are called on the class itself, not on its instances:
1class DinosaurDatabase {
2 static dinoCount = 0;
3
4 constructor(name, species) {
5 this.name = name;
6 this.species = species;
7 DinosaurDatabase.dinoCount++;
8 }
9
10 // Instance method - requires creating an object
11 getInfo() {
12 return `${this.name} (${this.species})`;
13 }
14
15 // Static method - called on the class, not on an instance
16 static getTotalDinosaurCount() {
17 return `Total number of dinosaurs in the database: ${DinosaurDatabase.dinoCount}`;
18 }
19
20 static compareAge(dino1, dino2) {
21 if (!dino1.age || !dino2.age) return "No age data available.";
22
23 if (dino1.age > dino2.age) {
24 return `${dino1.name} is older than ${dino2.name}.`;
25 } else if (dino1.age < dino2.age) {
26 return `${dino1.name} is younger than ${dino2.name}.`;
27 } else {
28 return `${dino1.name} and ${dino2.name} are the same age.`;
29 }
30 }
31}
32
33const dino1 = new DinosaurDatabase("Rex", "Tyrannosaurus");
34dino1.age = 8;
35
36const dino2 = new DinosaurDatabase("Blue", "Velociraptor");
37dino2.age = 4;
38
39const dino3 = new DinosaurDatabase("Trixie", "Triceratops");
40dino3.age = 6;
41
42console.log(DinosaurDatabase.getTotalDinosaurCount()); // "Total number of dinosaurs in the database: 3"
43console.log(DinosaurDatabase.compareAge(dino1, dino2)); // "Rex is older than Blue."
44console.log(DinosaurDatabase.compareAge(dino2, dino3)); // "Blue is younger than Trixie."Object.create()
The Object.create() method lets you create new objects with a specified prototype:
1// Prototype object for all dinosaurs
2const dinoPrototype = {
3 makeSound() {
4 return "Roar!";
5 },
6 eat() {
7 return `${this.name} is eating.`;
8 }
9};
10
11// Creating an object with dinoPrototype as its prototype
12const rex = Object.create(dinoPrototype);
13rex.name = "Rex";
14rex.species = "Tyrannosaurus";
15
16console.log(rex.name); // "Rex"
17console.log(rex.makeSound()); // "Roar!"
18console.log(rex.eat()); // "Rex is eating."Factory Functions
Factory functions are functions that create and return objects without using new:
1// Factory function for creating dinosaur objects
2function createDinosaur(name, species, diet) {
3 return {
4 name, // Shorthand syntax for name: name in ES6+
5 species,
6 diet,
7 health: 100,
8 hunger: 50,
9
10 feed() {
11 this.hunger -= 30;
12 if (this.hunger < 0) this.hunger = 0;
13 return `${this.name} has been fed. Hunger level: ${this.hunger}%`;
14 },
15
16 getStatus() {
17 return `${this.name} (${this.species}) - Health: ${this.health}%, Hunger: ${this.hunger}%`;
18 }
19 };
20}
21
22const blue = createDinosaur("Blue", "Velociraptor", "carnivore");
23const trixie = createDinosaur("Trixie", "Triceratops", "herbivore");
24
25console.log(blue.getStatus()); // "Blue (Velociraptor) - Health: 100%, Hunger: 50%"
26console.log(blue.feed()); // "Blue has been fed. Hunger level: 20%"Objects in Practice in Jurassic Park
Dinosaur Management System
1class DinosaurManager {
2 constructor() {
3 this.dinosaurs = [];
4 this.enclosures = [];
5 }
6
7 addDinosaur(dino) {
8 this.dinosaurs.push(dino);
9 console.log(`New dinosaur added: ${dino.name} (${dino.species})`);
10 }
11
12 addEnclosure(enclosure) {
13 this.enclosures.push(enclosure);
14 console.log(`New enclosure added: ${enclosure.name} (Capacity: ${enclosure.capacity})`);
15 }
16
17 assignDinosaurToEnclosure(dinoName, enclosureName) {
18 const dino = this.dinosaurs.find(d => d.name === dinoName);
19 const enclosure = this.enclosures.find(e => e.name === enclosureName);
20
21 if (!dino) {
22 return `Error: Dinosaur named ${dinoName} not found.`;
23 }
24
25 if (!enclosure) {
26 return `Error: Enclosure named ${enclosureName} not found.`;
27 }
28
29 if (enclosure.dinosaurs.length >= enclosure.capacity) {
30 return `Error: Enclosure ${enclosureName} has reached its maximum capacity.`;
31 }
32
33 // Check that predators are not mixed with herbivores
34 if (enclosure.dinosaurs.length > 0) {
35 const existingDiet = enclosure.dinosaurs[0].diet;
36 if (dino.diet === "carnivore" && existingDiet === "herbivore") {
37 return "Error: Predators cannot be placed with herbivores!";
38 }
39 if (dino.diet === "herbivore" && existingDiet === "carnivore") {
40 return "Error: Herbivores cannot be placed with predators!";
41 }
42 }
43
44 // Remove the dinosaur from its previous enclosure, if it was assigned to one
45 this.enclosures.forEach(e => {
46 const index = e.dinosaurs.findIndex(d => d.name === dinoName);
47 if (index !== -1) {
48 e.dinosaurs.splice(index, 1);
49 }
50 });
51
52 // Assign the dinosaur to the new enclosure
53 enclosure.dinosaurs.push(dino);
54 dino.enclosure = enclosureName;
55
56 return `${dinoName} has been assigned to enclosure ${enclosureName}.`;
57 }
58
59 getEnclosureReport(enclosureName) {
60 const enclosure = this.enclosures.find(e => e.name === enclosureName);
61
62 if (!enclosure) {
63 return `Error: Enclosure named ${enclosureName} not found.`;
64 }
65
66 let report = `=== ENCLOSURE REPORT: ${enclosure.name} ===
67Capacity: ${enclosure.dinosaurs.length}/${enclosure.capacity}
68Status: ${enclosure.status}
69Dinosaurs:\n`;
70
71 if (enclosure.dinosaurs.length === 0) {
72 report += "No dinosaurs in this enclosure.";
73 } else {
74 enclosure.dinosaurs.forEach(dino => {
75 report += `- ${dino.name} (${dino.species}): Health: ${dino.health}%, Hunger: ${dino.hunger}%\n`;
76 });
77 }
78
79 return report;
80 }
81}
82
83// Class for dinosaurs
84class Dinosaur {
85 constructor(name, species, diet) {
86 this.name = name;
87 this.species = species;
88 this.diet = diet;
89 this.health = 100;
90 this.hunger = 50;
91 this.enclosure = null; // Name of the enclosure the dinosaur is assigned to
92 }
93}
94
95// Class for enclosures
96class Enclosure {
97 constructor(name, capacity, security) {
98 this.name = name;
99 this.capacity = capacity;
100 this.security = security; // security level
101 this.status = "Operational";
102 this.dinosaurs = []; // List of dinosaurs in the enclosure
103 }
104}
105
106// Using the management system
107const parkManager = new DinosaurManager();
108
109// Creating enclosures
110const carnivoreEnclosure = new Enclosure("Paddock A", 3, "Maximum");
111const herbivoreEnclosure = new Enclosure("Paddock B", 5, "Standard");
112
113parkManager.addEnclosure(carnivoreEnclosure);
114parkManager.addEnclosure(herbivoreEnclosure);
115
116// Creating dinosaurs
117const rex = new Dinosaur("Rex", "Tyrannosaurus", "carnivore");
118const blue = new Dinosaur("Blue", "Velociraptor", "carnivore");
119const trixie = new Dinosaur("Trixie", "Triceratops", "herbivore");
120const spike = new Dinosaur("Spike", "Stegosaurus", "herbivore");
121
122parkManager.addDinosaur(rex);
123parkManager.addDinosaur(blue);
124parkManager.addDinosaur(trixie);
125parkManager.addDinosaur(spike);
126
127// Assigning dinosaurs to enclosures
128console.log(parkManager.assignDinosaurToEnclosure("Rex", "Paddock A"));
129console.log(parkManager.assignDinosaurToEnclosure("Blue", "Paddock A"));
130console.log(parkManager.assignDinosaurToEnclosure("Trixie", "Paddock B"));
131console.log(parkManager.assignDinosaurToEnclosure("Spike", "Paddock B"));
132
133// Attempting to assign a herbivore to the predator enclosure
134console.log(parkManager.assignDinosaurToEnclosure("Trixie", "Paddock A"));
135
136// Displaying the reports
137console.log(parkManager.getEnclosureReport("Paddock A"));
138console.log(parkManager.getEnclosureReport("Paddock B"));Summary
Objects are a fundamental part of the JavaScript language and let us model complex data structures and behavior. In Jurassic Park we use them to represent everything - from dinosaurs to the system that manages the whole park.
We have several ways to create objects:
- Object literals - the simplest way, ideal for single, unique objects
- Constructor functions - when we need to create many similar objects
- Classes (ES6+) - a modern, readable syntax for creating object templates with inheritance
- Object.create() - creating objects with a specified prototype
- Factory functions - functions that return new objects, an alternative to constructors
The choice of a particular technique depends on the situation and the needs of the project. In complex applications, like our Jurassic Park management system, we most often use a combination of these techniques.
Code for this lesson: index.js
1// Objects - creation - Jurassic Park
2console.log("JavaScript Objects Laboratory");
3console.log("Creating and constructing objects\n");
4
5// ===========================================
6// 1. OBJECT LITERALS (the simplest way)
7// ===========================================
8console.log("=== 1. Object literals ===");
9
10// Basic object
11const dinosaur1 = {
12 name: "T-Rex",
13 species: "Tyrannosaurus Rex",
14 age: 8,
15 weight: 8000,
16 carnivore: true
17};
18
19console.log("Dinosaur 1:");
20console.log(` Name: ${dinosaur1.name}`);
21console.log(` Species: ${dinosaur1.species}`);
22console.log(` Age: ${dinosaur1.age} years`);
23
24// Object with methods
25const dinosaur2 = {
26 name: "Blue",
27 species: "Velociraptor",
28 speed: 40,
29
30 // Traditional method
31 roar: function() {
32 return `${this.name} roars: SHREEK!`;
33 },
34
35 // Shorthand method (ES6)
36 run() {
37 return `${this.name} runs at a speed of ${this.speed} km/h`;
38 }
39};
40
41console.log("\nDinosaur 2:");
42console.log(` ${dinosaur2.roar()}`);
43console.log(` ${dinosaur2.run()}`);
44
45// ===========================================
46// 2. FUNCTION CONSTRUCTORS
47// ===========================================
48console.log("\n=== 2. Constructor functions ===");
49
50function Dinosaur(name, species, age, weight, carnivore) {
51 this.name = name;
52 this.species = species;
53 this.age = age;
54 this.weight = weight;
55 this.carnivore = carnivore;
56
57 this.getInfo = function() {
58 return `${this.name} (${this.species}) - ${this.age} years, ${this.weight}kg`;
59 };
60
61 this.roar = function() {
62 return `${this.name} says: ROAARRR!`;
63 };
64}
65
66const trex = new Dinosaur("Rexy", "T-Rex", 8, 8000, true);
67const trike = new Dinosaur("Trike", "Triceratops", 7, 9000, false);
68
69console.log("\nCreated via constructor:");
70console.log(` ${trex.getInfo()}`);
71console.log(` ${trex.roar()}`);
72console.log(` ${trike.getInfo()}`);
73
74// ===========================================
75// 3. Object.create()
76// ===========================================
77console.log("\n=== 3. Object.create() ===");
78
79const dinoPrototype = {
80 getInfo() {
81 return `${this.name} (${this.species})`;
82 },
83
84 roar() {
85 return `${this.name}: ROAARRR!`;
86 }
87};
88
89const velociraptor = Object.create(dinoPrototype);
90velociraptor.name = "Charlie";
91velociraptor.species = "Velociraptor";
92velociraptor.age = 5;
93
94console.log("\nCreated via Object.create():");
95console.log(` ${velociraptor.getInfo()}`);
96console.log(` ${velociraptor.roar()}`);
97
98// ===========================================
99// 4. ES6 CLASSES
100// ===========================================
101console.log("\n=== 4. ES6 Classes ===");
102
103class DinosaurClass {
104 constructor(name, species, age, weight, carnivore) {
105 this.name = name;
106 this.species = species;
107 this.age = age;
108 this.weight = weight;
109 this.carnivore = carnivore;
110 }
111
112 getInfo() {
113 return `${this.name} (${this.species}) - ${this.age} years, ${this.weight}kg`;
114 }
115
116 roar() {
117 return `${this.name} says: ROAARRR!`;
118 }
119
120 isHeavy() {
121 return this.weight > 1000;
122 }
123}
124
125const stego = new DinosaurClass("Stego", "Stegosaurus", 6, 5000, false);
126const brachio = new DinosaurClass("Brachio", "Brachiosaurus", 10, 50000, false);
127
128console.log("\nCreated via class:");
129console.log(` ${stego.getInfo()}`);
130console.log(` Is it heavy? ${stego.isHeavy()}`);
131console.log(` ${brachio.getInfo()}`);
132console.log(` Is it heavy? ${brachio.isHeavy()}`);
133
134// ===========================================
135// 5. FACTORY FUNCTIONS
136// ===========================================
137console.log("\n=== 5. Factory functions ===");
138
139function createDinosaur(name, species, options = {}) {
140 return {
141 name,
142 species,
143 age: options.age || 5,
144 weight: options.weight || 100,
145 carnivore: options.carnivore || false,
146 sector: options.sector || "A",
147
148 getInfo() {
149 return `${this.name} (${this.species}) - Sector ${this.sector}`;
150 },
151
152 feed() {
153 console.log(`Feeding ${this.name}`);
154 }
155 };
156}
157
158const dilo = createDinosaur("Dilo", "Dilophosaurus", {
159 age: 4,
160 weight: 400,
161 carnivore: true,
162 sector: "E"
163});
164
165console.log("\nCreated via factory:");
166console.log(` ${dilo.getInfo()}`);
167dilo.feed();
168
169// ===========================================
170// 6. NESTED OBJECTS
171// ===========================================
172console.log("\n=== 6. Nested objects ===");
173
174const park = {
175 name: "Jurassic Park",
176 location: "Isla Nublar",
177
178 sectors: {
179 A: { name: "Carnivore Zone", capacity: 5, current: 2 },
180 B: { name: "Raptor Pen", capacity: 10, current: 3 },
181 C: { name: "Herbivore Valley", capacity: 20, current: 8 }
182 },
183
184 stats: {
185 totalDinosaurs: 13,
186 totalVisitors: 1500,
187 securityLevel: "HIGH"
188 },
189
190 getReport() {
191 console.log(`\nPark report for ${this.name}:`);
192 console.log(` Location: ${this.location}`);
193 console.log(` Dinosaurs: ${this.stats.totalDinosaurs}`);
194 console.log(` Visitors: ${this.stats.totalVisitors}`);
195 console.log(` Security: ${this.stats.securityLevel}`);
196 }
197};
198
199park.getReport();
200
201console.log("\nSectors:");
202Object.entries(park.sectors).forEach(([key, sector]) => {
203 console.log(` ${key}: ${sector.name} - ${sector.current}/${sector.capacity}`);
204});
205
206// ===========================================
207// 7. GETTERS AND SETTERS
208// ===========================================
209console.log("\n=== 7. Getters and setters ===");
210
211class ManagedDinosaur {
212 constructor(name, species, health) {
213 this.name = name;
214 this.species = species;
215 this._health = health; // Private property (by convention)
216 }
217
218 // Getter
219 get health() {
220 return this._health;
221 }
222
223 // Setter with validation
224 set health(value) {
225 if (value < 0) value = 0;
226 if (value > 100) value = 100;
227 this._health = value;
228 console.log(` Health of ${this.name} changed to ${this._health}%`);
229 }
230
231 get status() {
232 if (this._health >= 80) return "Healthy";
233 if (this._health >= 50) return "Medium";
234 return "Critical";
235 }
236}
237
238const managedDino = new ManagedDinosaur("Rex", "T-Rex", 75);
239console.log(`\n${managedDino.name}:`);
240console.log(` Health: ${managedDino.health}%`);
241console.log(` Status: ${managedDino.status}`);
242
243managedDino.health = 95;
244console.log(` New status: ${managedDino.status}`);
245
246managedDino.health = 150; // Will be capped at 100
247console.log(` Status after exceeding the limit: ${managedDino.status}`);
248
249// ===========================================
250// 8. STATIC METHODS AND PROPERTIES
251// ===========================================
252console.log("\n=== 8. Static methods and properties ===");
253
254class DinoSpecies {
255 static species = [
256 "Tyrannosaurus Rex",
257 "Velociraptor",
258 "Triceratops",
259 "Stegosaurus",
260 "Brachiosaurus"
261 ];
262
263 static isCarnivore(species) {
264 const carnivores = ["Tyrannosaurus Rex", "Velociraptor", "Spinosaurus"];
265 return carnivores.includes(species);
266 }
267
268 static getInfo(species) {
269 const info = {
270 "Tyrannosaurus Rex": { weight: 8000, period: "Cretaceous" },
271 "Velociraptor": { weight: 80, period: "Cretaceous" },
272 "Triceratops": { weight: 9000, period: "Cretaceous" }
273 };
274 return info[species] || { weight: "?", period: "?" };
275 }
276
277 static listAll() {
278 console.log("\nAll species:");
279 this.species.forEach((s, i) => {
280 const carnivore = this.isCarnivore(s) ? "carnivore" : "herbivore";
281 console.log(` ${i + 1}. ${carnivore} ${s}`);
282 });
283 }
284}
285
286DinoSpecies.listAll();
287
288console.log("\nChecking species:");
289console.log(` T-Rex carnivore? ${DinoSpecies.isCarnivore("Tyrannosaurus Rex")}`);
290console.log(` Triceratops carnivore? ${DinoSpecies.isCarnivore("Triceratops")}`);
291
292const trexInfo = DinoSpecies.getInfo("Tyrannosaurus Rex");
293console.log(`\nInfo about T-Rex: weight ${trexInfo.weight}kg, period ${trexInfo.period}`);
294
295// ===========================================
296// 9. INHERITANCE
297// ===========================================
298console.log("\n=== 9. Inheritance ===");
299
300class Animal {
301 constructor(name, age) {
302 this.name = name;
303 this.age = age;
304 }
305
306 breathe() {
307 return `${this.name} breathes`;
308 }
309
310 getAge() {
311 return `${this.name} is ${this.age} years old`;
312 }
313}
314
315class Carnivore extends Animal {
316 constructor(name, age, huntingSkill) {
317 super(name, age);
318 this.huntingSkill = huntingSkill;
319 this.type = "Carnivore";
320 }
321
322 hunt() {
323 return `${this.name} hunts (skill: ${this.huntingSkill}/10)`;
324 }
325
326 roar() {
327 return `${this.name} roars: ROAARRR!`;
328 }
329}
330
331class Herbivore extends Animal {
332 constructor(name, age, plantPreference) {
333 super(name, age);
334 this.plantPreference = plantPreference;
335 this.type = "Herbivore";
336 }
337
338 eat() {
339 return `${this.name} eats ${this.plantPreference}`;
340 }
341
342 graze() {
343 return `${this.name} peacefully grazes`;
344 }
345}
346
347const rex = new Carnivore("Rexy", 8, 10);
348const trico = new Herbivore("Trico", 7, "ferns");
349
350console.log("\nCarnivore:");
351console.log(` ${rex.getAge()}`);
352console.log(` ${rex.breathe()}`);
353console.log(` ${rex.hunt()}`);
354console.log(` ${rex.roar()}`);
355
356console.log("\nHerbivore:");
357console.log(` ${trico.getAge()}`);
358console.log(` ${trico.breathe()}`);
359console.log(` ${trico.eat()}`);
360console.log(` ${trico.graze()}`);
361
362// ===========================================
363// 10. COMPLEX EXAMPLE
364// ===========================================
365console.log("\n=== 10. Management system - complex example ===");
366
367class ParkManagementSystem {
368 constructor(parkName) {
369 this.parkName = parkName;
370 this.dinosaurs = new Map();
371 this.nextId = 1;
372 }
373
374 addDinosaur(name, species, options = {}) {
375 const dino = {
376 id: this.nextId++,
377 name,
378 species,
379 age: options.age || 5,
380 weight: options.weight || 1000,
381 health: options.health || 100,
382 sector: options.sector || "A",
383 carnivore: options.carnivore || false,
384 fed: false,
385 lastCheckup: new Date()
386 };
387
388 this.dinosaurs.set(dino.id, dino);
389 console.log(`Added: ${name} (#${dino.id})`);
390 return dino.id;
391 }
392
393 getDinosaur(id) {
394 return this.dinosaurs.get(id);
395 }
396
397 removeDinosaur(id) {
398 const dino = this.dinosaurs.get(id);
399 if (dino) {
400 this.dinosaurs.delete(id);
401 console.log(`Removed: ${dino.name} (#${id})`);
402 return true;
403 }
404 return false;
405 }
406
407 feedDinosaur(id) {
408 const dino = this.dinosaurs.get(id);
409 if (dino) {
410 dino.fed = true;
411 console.log(`Fed: ${dino.name}`);
412 }
413 }
414
415 updateHealth(id, newHealth) {
416 const dino = this.dinosaurs.get(id);
417 if (dino) {
418 dino.health = Math.max(0, Math.min(100, newHealth));
419 console.log(`Updated health of ${dino.name}: ${dino.health}%`);
420 }
421 }
422
423 getStats() {
424 const dinos = Array.from(this.dinosaurs.values());
425
426 return {
427 total: dinos.length,
428 carnivores: dinos.filter(d => d.carnivore).length,
429 avgHealth: (dinos.reduce((sum, d) => sum + d.health, 0) / dinos.length).toFixed(1),
430 fed: dinos.filter(d => d.fed).length,
431 bySector: dinos.reduce((acc, d) => {
432 acc[d.sector] = (acc[d.sector] || 0) + 1;
433 return acc;
434 }, {})
435 };
436 }
437
438 displayReport() {
439 console.log(`\n============================================================`);
440 console.log(`PARK REPORT: ${this.parkName}`);
441 console.log("=".repeat(60));
442
443 const stats = this.getStats();
444 console.log("\nStatistics:");
445 console.log(` Total dinosaurs: ${stats.total}`);
446 console.log(` Carnivores: ${stats.carnivores}`);
447 console.log(` Average health: ${stats.avgHealth}%`);
448 console.log(` Fed: ${stats.fed}/${stats.total}`);
449
450 console.log("\nBreakdown by sector:");
451 Object.entries(stats.bySector).sort().forEach(([sector, count]) => {
452 console.log(` Sector ${sector}: ${count}`);
453 });
454
455 console.log("\nDinosaur list:");
456 Array.from(this.dinosaurs.values())
457 .sort((a, b) => a.id - b.id)
458 .forEach(dino => {
459 const icon = dino.carnivore ? "carnivore" : "herbivore";
460 const fedStatus = dino.fed ? "β" : "Γ";
461 console.log(` #${dino.id} ${icon} ${dino.name} (${dino.species})`);
462 console.log(` Sector ${dino.sector} | Health: ${dino.health}% | Fed: ${fedStatus}`);
463 });
464 }
465}
466
467// System demonstration
468console.log();
469const parkSystem = new ParkManagementSystem("Isla Nublar");
470
471const id1 = parkSystem.addDinosaur("Rexy", "T-Rex", { age: 8, weight: 8000, sector: "A", carnivore: true });
472const id2 = parkSystem.addDinosaur("Blue", "Velociraptor", { age: 5, weight: 80, sector: "B", carnivore: true, health: 100 });
473const id3 = parkSystem.addDinosaur("Charlie", "Velociraptor", { age: 5, weight: 80, sector: "B", carnivore: true, health: 85 });
474const id4 = parkSystem.addDinosaur("Trike", "Triceratops", { age: 7, weight: 9000, sector: "C", health: 70 });
475const id5 = parkSystem.addDinosaur("Stego", "Stegosaurus", { age: 6, weight: 5000, sector: "C" });
476
477console.log();
478parkSystem.feedDinosaur(id1);
479parkSystem.feedDinosaur(id2);
480parkSystem.updateHealth(id4, 85);
481
482parkSystem.displayReport();
483
484console.log("\nCongratulations! You've mastered creating objects!");Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. What are the two ways to access object properties in JavaScript?
2. What does the 'new' keyword do before calling a constructor function?
Hands-on tasks in the game
- Click in order
Arrange the elements of creating a dinosaur object with a method:
- Code editor
Create an object dinosaur with the properties name: 'Rexy', species: 'Tyrannosaurus Rex', age: 25 and isCarnivore: true, and with a nested object stats that has the property health: 95. After creating the object, add a property enclosure with the value 'Zone A'. Display name using dot notation and species using bracket notation in the console.
- Horizontal ordering
Arrange the elements of creating an object with a literal:
- Click in order
Arrange the elements of an object declaration with properties:
- Horizontal ordering
Arrange the elements of an object declaration in JavaScript