JavaScript and TypeScript course Β· Module 2: Functions, Arrays and Objects

Creating Objects (Literals, Constructors)

11 min read
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); // 64

Accessing 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); // undefined

Constructors 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:

  1. Consistency - all objects have the same set of properties and methods
  2. Scalability - it is easier to create many similar objects
  3. 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:

  1. Object literals - the simplest way, ideal for single, unique objects
  2. Constructor functions - when we need to create many similar objects
  3. Classes (ES6+) - a modern, readable syntax for creating object templates with inheritance
  4. Object.create() - creating objects with a specified prototype
  5. 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. 1. What are the two ways to access object properties in JavaScript?

  2. 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

Useful articles