In Jurassic Park we use JavaScript objects to represent many elements of our ecosystem - from dinosaurs and their behaviors, to park areas, to staff data and safety procedures. Objects are a fundamental data type in JavaScript, enabling the creation of complex data structures with properties and methods.
The simplest way to create objects in JavaScript is using an object literal - the curly brace
{} notation.1// Simple dinosaur object created with 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); // 64We can access object properties in two ways:
1// Dot notation
2console.log(velociraptor.diet); // "carnivore"
3
4// Bracket notation (useful when property name is stored in a variable)
5const propertyName = "location";
6console.log(velociraptor[propertyName]); // "Sector B"
7
8// Bracket notation is also useful when 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"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 to feed 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 was 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 checking 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" : "Requires veterinary care"}`;
31 }
32};
33
34console.log(velociraptor.makeSound()); // "Blue makes a sharp, piercing sound!"
35console.log(velociraptor.feed()); // "Blue was fed. Hunger level: 20%"
36console.log(velociraptor.checkStatus());The
this keyword in methods refers to the object on which the method is called.We can dynamically add and remove properties from JavaScript objects:
1const rex = {
2 name: "Rex",
3 species: "Tyrannosaurus Rex"
4};
5
6// Adding properties
7rex.age = 12;
8rex.health = 100;
9rex.zone = "A";
10rex["last-feeding"] = "2024-01-15";
11
12console.log(rex);
13// { name: "Rex", species: "Tyrannosaurus Rex", age: 12, health: 100, zone: "A", "last-feeding": "2024-01-15" }
14
15// Removing a property
16delete rex.zone;
17console.log(rex.zone); // undefinedWhen we need to create multiple objects with the same structure, we use constructor functions. They are called with the
new keyword:1// Constructor function (convention: capitalize first letter)
2function Dinosaur(name, species, weight, isDangerous) {
3 // `this` refers to the new object being created
4 this.name = name;
5 this.species = species;
6 this.weight = weight;
7 this.isDangerous = isDangerous;
8 this.health = 100;
9 this.hunger = 0;
10
11 // Method defined in constructor
12 this.feed = function() {
13 this.hunger = Math.max(0, this.hunger - 30);
14 return `${this.name} was fed. Hunger: ${this.hunger}%`;
15 };
16
17 this.roar = function() {
18 return `${this.name} (${this.species}) roars!`;
19 };
20}
21
22// Creating instances with `new`
23const rex = new Dinosaur("Rex", "T-Rex", 8000, true);
24const blue = new Dinosaur("Blue", "Velociraptor", 15, true);
25const stego = new Dinosaur("Stego", "Stegosaurus", 3500, false);
26
27console.log(rex.name); // "Rex"
28console.log(blue.species); // "Velociraptor"
29console.log(stego.isDangerous); // false
30
31rex.roar(); // "Rex (T-Rex) roars!"
32blue.feed(); // "Blue was fed. Hunger: 0%"
33
34// instanceof check
35console.log(rex instanceof Dinosaur); // true
36console.log(blue instanceof Dinosaur); // trueES6 introduced cleaner class syntax - under the hood it's still the same prototype-based mechanism:
1class Dinosaur {
2 constructor(name, species, weight, isDangerous = false) {
3 this.name = name;
4 this.species = species;
5 this.weight = weight;
6 this.isDangerous = isDangerous;
7 this.health = 100;
8 this.hunger = 0;
9 }
10
11 feed(amount = 30) {
12 this.hunger = Math.max(0, this.hunger - amount);
13 return `${this.name} was fed. Hunger: ${this.hunger}%`;
14 }
15
16 roar() {
17 return `${this.name} (${this.species}) roars!`;
18 }
19
20 getStatus() {
21 return {
22 name: this.name,
23 health: this.health,
24 hunger: this.hunger,
25 condition: this.health > 80 ? 'Excellent' : 'Requires attention'
26 };
27 }
28}
29
30const rex = new Dinosaur("Rex", "T-Rex", 8000, true);
31rex.feed();
32console.log(rex.getStatus());
33// { name: 'Rex', health: 100, hunger: 0, condition: 'Excellent' }Classes make implementing inheritance straightforward:
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 // Call the parent class constructor
18 super(name, species);
19 this.diet = diet;
20 this.health = 100;
21 }
22
23 // Override the parent method
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 // Add new methods
33 eat(food) {
34 if (this.diet === "carnivore" && food.type === "meat") {
35 return `${this.name} devours ${food.name} with appetite!`;
36 } else if (this.diet === "herbivore" && food.type === "plant") {
37 return `${this.name} nibbles on ${food.name} contentedly.`;
38 } else {
39 return `${this.name} is not interested in eating ${food.name}.`;
40 }
41 }
42}
43
44// Food objects
45const meat = { name: "meat", type: "meat" };
46const plants = { name: "plants", type: "plant" };
47
48// 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 devours meat with appetite!"
56console.log(rex.eat(plants)); // "Rex is not interested in eating plants."
57console.log(spike.eat(plants)); // "Spike nibbles on plants contentedly."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 dinosaurs in the database: ${DinosaurDatabase.dinoCount}`;
18 }
19
20 static compareAge(dino1, dino2) {
21 if (!dino1.age || !dino2.age) return "Age data missing.";
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 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() creates a new object with a specified prototype:1const dinosaurPrototype = {
2 makeSound() {
3 return `${this.name} makes a sound!`;
4 },
5 eat(food) {
6 return `${this.name} eats ${food}`;
7 }
8};
9
10const rex = Object.create(dinosaurPrototype);
11rex.name = "Rex";
12rex.species = "T-Rex";
13
14console.log(rex.makeSound()); // "Rex makes a sound!"
15console.log(rex.eat("meat")); // "Rex eats meat"Factory functions return new objects - an alternative to constructors and classes:
1function createDinosaur(name, species, weight) {
2 // Private variable - not accessible from outside
3 let _health = 100;
4 let _hunger = 0;
5
6 // Public interface
7 return {
8 name,
9 species,
10 weight,
11
12 feed() {
13 _hunger = Math.max(0, _hunger - 30);
14 return `${name} was fed`;
15 },
16
17 getHealth() { return _health; },
18 getHunger() { return _hunger; },
19
20 takeDamage(amount) {
21 _health = Math.max(0, _health - amount);
22 return _health;
23 }
24 };
25}
26
27const rex = createDinosaur("Rex", "T-Rex", 8000);
28rex.feed();
29console.log(rex.getHunger()); // 0
30// console.log(rex._hunger); // undefined - private!1class DinosaurManager {
2 constructor(parkName) {
3 this.parkName = parkName;
4 this.dinosaurs = new Map();
5 this.zones = new Map();
6 }
7
8 addDinosaur(dino) {
9 this.dinosaurs.set(dino.name, dino);
10 console.log(`${dino.name} registered in ${this.parkName}`);
11 return this;
12 }
13
14 addZone(zoneId, type) {
15 this.zones.set(zoneId, { type, dinosaurs: [] });
16 return this;
17 }
18
19 assignToZone(dinoName, zoneId) {
20 const dino = this.dinosaurs.get(dinoName);
21 const zone = this.zones.get(zoneId);
22
23 if (!dino || !zone) {
24 throw new Error(`Dinosaur ${dinoName} or zone ${zoneId} not found`);
25 }
26
27 dino.zone = zoneId;
28 zone.dinosaurs.push(dinoName);
29 console.log(`${dinoName} assigned to zone ${zoneId}`);
30 return this;
31 }
32
33 getZoneReport(zoneId) {
34 const zone = this.zones.get(zoneId);
35 if (!zone) return null;
36
37 return {
38 zoneId,
39 type: zone.type,
40 count: zone.dinosaurs.length,
41 dinosaurs: zone.dinosaurs.map(name => {
42 const d = this.dinosaurs.get(name);
43 return `${d.name} (${d.species})`;
44 })
45 };
46 }
47}
48
49const manager = new DinosaurManager("Jurassic Park");
50manager
51 .addZone("A", "CARNIVORES")
52 .addZone("B", "HERBIVORES");
53
54const rex = new Dinosaur("Rex", "T-Rex", 8000, true);
55const stego = new Dinosaur("Stego", "Stegosaurus", 3500, false);
56
57manager
58 .addDinosaur(rex)
59 .addDinosaur(stego)
60 .assignToZone("Rex", "A")
61 .assignToZone("Stego", "B");
62
63console.log(manager.getZoneReport("A"));
64// { zoneId: 'A', type: 'CARNIVORES', count: 1, dinosaurs: ['Rex (T-Rex)'] }Objects are a fundamental element of JavaScript and allow us to model complex data structures and behaviors. In Jurassic Park, we use them to represent everything - from dinosaurs to the entire park management system.
We have several ways to create objects:
The choice of technique depends on the situation and project needs. In complex applications like our Jurassic Park management system, we typically use a combination of these techniques.
"Objects are like dinosaur DNA files in our lab" - says Dr. Rex. "Each file (object) contains properties (DNA data) and methods (how the organism behaves). Constructor functions and classes are like templates for creating new files - once you define the structure, you can use it to create many similar objects!"