In Jurassic Park, efficiently managing different dinosaur species requires understanding the similarities between them and the ability to inherit traits. JavaScript uses prototypes to implement an inheritance mechanism — it is one of the most unique and powerful aspects of the language. Understanding prototypes and prototypal inheritance is key to writing efficient, flexible JavaScript code.
In JavaScript, every object has an internal property called a prototype, which is a reference to another object. When we try to access a property of an object, JavaScript first checks whether the object itself has such a property. If not, it checks the object's prototype, then the prototype's prototype, and so on, forming the so-called prototype chain.
1// Creating a simple object
2const dinosaur = {
3 species: "Tyrannosaurus",
4 makesSound: true,
5 roar() {
6 return "ROOOOAR!";
7 }
8};
9
10// Creating a new object that inherits from dinosaur
11const rex = Object.create(dinosaur);
12rex.name = "Rex";
13rex.age = 8;
14
15// rex has access to its own properties
16console.log(rex.name); // "Rex"
17console.log(rex.age); // 8
18
19// rex also has access to dinosaur's properties and methods
20console.log(rex.species); // "Tyrannosaurus"
21console.log(rex.makesSound); // true
22console.log(rex.roar()); // "ROOOOAR!"
23
24// Let's check if rex has its own 'species' property (it doesn't)
25console.log(rex.hasOwnProperty('species')); // false
26
27// But it does have its own 'name' property
28console.log(rex.hasOwnProperty('name')); // trueIn the example above,
rex does not have its own species property, but accessing rex.species works because JavaScript looks for this property in the prototype of rex, which is the dinosaur object.Prototypes form a chain that JavaScript traverses when we try to access a property. This mechanism is called the prototype chain.
Every object in JavaScript has an internal link to its prototype (
__proto__ or via Object.getPrototypeOf):1const dinosaur = {
2 breathe() { return `${this.name} breathes`; },
3 sleep() { return `${this.name} sleeps`; }
4};
5
6const rex = Object.create(dinosaur);
7rex.name = 'Rex';
8rex.species = 'T-Rex';
9
10console.log(rex.breathe()); // "Rex breathes" - from prototype!
11console.log(rex.sleep()); // "Rex sleeps" - from prototype!
12console.log(rex.hasOwnProperty('name')); // true - own property
13console.log(rex.hasOwnProperty('breathe')); // false - inherited!
14
15// Checking prototype
16console.log(Object.getPrototypeOf(rex) === dinosaur); // trueMethods on the prototype are shared between all instances (more efficient than in-constructor methods):
1function Dinosaur(name, species) {
2 this.name = name;
3 this.species = species;
4 this.health = 100;
5}
6
7// Methods on prototype - shared by all instances
8Dinosaur.prototype.roar = function() {
9 return `${this.name} roars!`;
10};
11
12Dinosaur.prototype.eat = function(food) {
13 return `${this.name} eats ${food}`;
14};
15
16const rex = new Dinosaur('Rex', 'T-Rex');
17const blue = new Dinosaur('Blue', 'Velociraptor');
18
19// Both share the SAME roar function (not two copies)
20console.log(rex.roar === blue.roar); // true - same function!
21console.log(rex.roar()); // "Rex roars!"
22console.log(blue.roar()); // "Blue roars!"In this example, the
roar and eat methods are defined on the prototype of the Dinosaur constructor function. All instances created with new Dinosaur() share the same methods, which is much more efficient than defining those methods in the constructor for each instance separately.We can check an object's prototype using several methods:
1// Using Object.getPrototypeOf()
2console.log(Object.getPrototypeOf(rex) === Dinosaur.prototype); // true
3
4// Using __proto__ (deprecated property, not recommended in production code)
5console.log(rex.__proto__ === Dinosaur.prototype); // true
6
7// Checking if an object is an instance of a constructor
8console.log(rex instanceof Dinosaur); // true
9console.log(rex instanceof Object); // true (all objects inherit from Object.prototype)We can implement inheritance between constructor functions by linking their prototypes:
1// Constructor function for Animal (base class)
2function Animal(name) {
3 this.name = name;
4 this.isAlive = true;
5}
6
7Animal.prototype.eat = function(food) {
8 return `${this.name} eats ${food}.`;
9};
10
11Animal.prototype.sleep = function() {
12 return `${this.name} sleeps.`;
13};
14
15// Constructor function for Dinosaur (derived class)
16function Dinosaur(name, species, diet) {
17 // Call the base class constructor
18 Animal.call(this, name);
19
20 // Add Dinosaur-specific properties
21 this.species = species;
22 this.diet = diet;
23 this.isExtinct = false;
24}
25
26// Set Dinosaur's prototype to inherit from Animal.prototype
27Dinosaur.prototype = Object.create(Animal.prototype);
28
29// Restore the correct constructor property
30Dinosaur.prototype.constructor = Dinosaur;
31
32// Add Dinosaur-specific methods
33Dinosaur.prototype.roar = function() {
34 const volume = this.diet === "carnivore" ? "loudly" : "softly";
35 return `${this.name} roars ${volume}!`;
36};
37
38// Create a Dinosaur instance
39const velociraptor = new Dinosaur("Blue", "Velociraptor", "carnivore");
40
41// We have access to Animal methods
42console.log(velociraptor.eat("meat")); // "Blue eats meat."
43console.log(velociraptor.sleep()); // "Blue sleeps."
44
45// And to Dinosaur-specific methods
46console.log(velociraptor.roar()); // "Blue roars loudly!"
47
48// Checking the prototype chain
49console.log(velociraptor instanceof Dinosaur); // true
50console.log(velociraptor instanceof Animal); // true
51console.log(velociraptor instanceof Object); // trueThis pattern of implementing inheritance between constructors is often called "pseudo-classical inheritance" because it emulates class-based inheritance in a language that originally relies on prototypes.
1// Base type
2function Creature(name) {
3 this.name = name;
4 this.alive = true;
5}
6Creature.prototype.breathe = function() {
7 return `${this.name} breathes`;
8};
9
10// Dinosaur extends Creature
11function DinosaurOld(name, species) {
12 Creature.call(this, name); // call parent constructor
13 this.species = species;
14}
15// Set up prototype chain
16DinosaurOld.prototype = Object.create(Creature.prototype);
17DinosaurOld.prototype.constructor = DinosaurOld;
18
19DinosaurOld.prototype.roar = function() {
20 return `${this.name} roars!`;
21};
22
23// Carnivore extends Dinosaur
24function Carnivore(name, species, huntingRange) {
25 DinosaurOld.call(this, name, species);
26 this.huntingRange = huntingRange;
27}
28Carnivore.prototype = Object.create(DinosaurOld.prototype);
29Carnivore.prototype.constructor = Carnivore;
30
31Carnivore.prototype.hunt = function() {
32 return `${this.name} hunts in a ${this.huntingRange}km range!`;
33};
34
35const carnivore = new Carnivore('Rex', 'T-Rex', 5);
36console.log(carnivore.breathe()); // "Rex breathes" - from Creature
37console.log(carnivore.roar()); // "Rex roars!" - from Dinosaur
38console.log(carnivore.hunt()); // "Rex hunts in a 5km range!" - own
39
40console.log(carnivore instanceof Carnivore); // true
41console.log(carnivore instanceof DinosaurOld); // true
42console.log(carnivore instanceof Creature); // trueClasses in ES6 are syntactic sugar over the prototype system - cleaner, but equivalent:
1class Creature {
2 constructor(name) {
3 this.name = name;
4 this.alive = true;
5 }
6
7 breathe() {
8 return `${this.name} breathes`;
9 }
10
11 toString() {
12 return `[Creature: ${this.name}]`;
13 }
14}
15
16class Dinosaur extends Creature {
17 constructor(name, species) {
18 super(name); // calls Creature constructor
19 this.species = species;
20 this.health = 100;
21 }
22
23 roar() {
24 return `${this.name} (${this.species}) roars!`;
25 }
26
27 // Override parent method
28 toString() {
29 return `[Dinosaur: ${this.name} (${this.species})]`;
30 }
31}
32
33class Carnivore extends Dinosaur {
34 constructor(name, species, huntingRange) {
35 super(name, species);
36 this.huntingRange = huntingRange;
37 this.diet = 'carnivore';
38 }
39
40 hunt(prey) {
41 return `${this.name} hunts ${prey} in ${this.huntingRange}km range!`;
42 }
43}
44
45class Herbivore extends Dinosaur {
46 constructor(name, species, favoriteFood) {
47 super(name, species);
48 this.favoriteFood = favoriteFood;
49 this.diet = 'herbivore';
50 }
51
52 graze() {
53 return `${this.name} grazes on ${this.favoriteFood}`;
54 }
55}
56
57class Tyrannosaurus extends Carnivore {
58 constructor(name) {
59 super(name, 'T-Rex', 5);
60 this.biteForce = 57000; // Newtons
61 }
62
63 stomp() {
64 return `${this.name} stomps the ground - everything shakes!`;
65 }
66}
67
68class Velociraptor extends Carnivore {
69 constructor(name) {
70 super(name, 'Velociraptor', 3);
71 this.intelligence = 'HIGH';
72 this.packHunter = true;
73 }
74
75 coordinateAttack(packMembers) {
76 return `${this.name} coordinates attack with: ${packMembers.join(', ')}`;
77 }
78}
79
80class Triceratops extends Herbivore {
81 constructor(name) {
82 super(name, 'Triceratops', 'ferns');
83 this.hornLength = 1; // meters
84 }
85
86 chargeAttack() {
87 return `${this.name} charges with ${this.hornLength}m horns!`;
88 }
89}
90
91class Brachiosaurus extends Herbivore {
92 constructor(name) {
93 super(name, 'Brachiosaurus', 'treetops');
94 this.neckLength = 9; // meters
95 }
96
97 eatTrees() {
98 return `${this.name} reaches ${this.neckLength}m up to eat from treetops`;
99 }
100}
101
102// Full Jurassic Park simulation
103const rex = new Tyrannosaurus('Rex');
104const blue = new Velociraptor('Blue');
105const delta = new Velociraptor('Delta');
106const trike = new Triceratops('Trike');
107const brachie = new Brachiosaurus('Brachie');
108
109console.log(rex.breathe()); // "Rex breathes" - from Creature
110console.log(rex.roar()); // "Rex (T-Rex) roars!" - from Dinosaur
111console.log(rex.hunt('Trike')); // "Rex hunts Trike in 5km range!" - from Carnivore
112console.log(rex.stomp()); // own method
113
114console.log(blue.coordinateAttack(['Delta', 'Echo', 'Charlie']));
115
116// instanceof chain
117console.log(rex instanceof Tyrannosaurus); // true
118console.log(rex instanceof Carnivore); // true
119console.log(rex instanceof Dinosaur); // true
120console.log(rex instanceof Creature); // trueJavaScript doesn't support multiple inheritance, but mixins let you mix in functionality from multiple sources:
1// Mixin - a set of methods to add to a class
2const SwimMixin = {
3 swim(speed) {
4 return `${this.name} swims at ${speed} km/h!`;
5 },
6 dive(depth) {
7 return `${this.name} dives to ${depth} meters!`;
8 }
9};
10
11const FlyMixin = {
12 fly(altitude) {
13 return `${this.name} flies at ${altitude}m altitude!`;
14 },
15 land() {
16 return `${this.name} lands!`;
17 }
18};
19
20// Apply mixins to a class
21class Pteranodon extends Dinosaur {
22 constructor(name) {
23 super(name, 'Pteranodon');
24 this.wingspan = 7; // meters
25 }
26}
27
28// Apply mixins
29Object.assign(Pteranodon.prototype, FlyMixin, SwimMixin);
30
31const ptero = new Pteranodon('Ptero');
32console.log(ptero.fly(200)); // "Ptero flies at 200m altitude!"
33console.log(ptero.dive(10)); // "Ptero dives to 10 meters!"
34console.log(ptero.roar()); // "Ptero (Pteranodon) roars!" - from DinosaurAll objects inherit from
Object.prototype:1const dino = { name: 'Rex', species: 'T-Rex' };
2
3// Methods from Object.prototype
4console.log(dino.hasOwnProperty('name')); // true
5console.log(dino.hasOwnProperty('breathe')); // false
6
7console.log(dino.toString()); // "[object Object]" - can be overridden
8
9// Object static methods
10console.log(Object.keys(dino)); // ['name', 'species']
11console.log(Object.values(dino)); // ['Rex', 'T-Rex']
12console.log(Object.entries(dino)); // [['name', 'Rex'], ['species', 'T-Rex']]
13
14const copy = Object.assign({}, dino, { health: 100 });
15const spread = { ...dino, health: 100 };Below is a more complex example of a dinosaur management system using prototypal inheritance:
1// Base class for all creatures in the park
2class Creature {
3 constructor(name, age) {
4 this.name = name;
5 this.age = age;
6 this.health = 100;
7 this.alive = true;
8 }
9
10 eat(food) {
11 this.health = Math.min(100, this.health + 10);
12 return `${this.name} eats ${food}. Health: ${this.health}%`;
13 }
14
15 sleep() {
16 this.health = Math.min(100, this.health + 5);
17 return `${this.name} sleeps. Health: ${this.health}%`;
18 }
19
20 damage(amount) {
21 this.health = Math.max(0, this.health - amount);
22 if (this.health === 0 && this.alive) {
23 this.alive = false;
24 return `${this.name} is dead!`;
25 }
26 return `${this.name} takes ${amount} damage. Remaining health: ${this.health}%`;
27 }
28}
29
30// Class for dinosaurs, inheriting from Creature
31class Dinosaur extends Creature {
32 constructor(name, species, age, diet) {
33 super(name, age);
34 this.species = species;
35 this.diet = diet;
36 this.containmentLevel = this.calculateContainmentLevel();
37 }
38
39 calculateContainmentLevel() {
40 if (this.diet === "carnivore") {
41 return this.age > 5 ? "Maximum" : "High";
42 } else {
43 return this.age > 10 ? "Medium" : "Standard";
44 }
45 }
46
47 roar() {
48 const volume = this.diet === "carnivore" ? "loudly" : "softly";
49 return `${this.name} roars ${volume}!`;
50 }
51
52 getStatus() {
53 return `
54Dinosaur: ${this.name} (${this.species})
55Age: ${this.age} years
56Diet: ${this.diet === "carnivore" ? "Carnivore" : "Herbivore"}
57Health: ${this.health}%
58Status: ${this.alive ? "Alive" : "Dead"}
59Containment level: ${this.containmentLevel}
60`;
61 }
62}
63
64// Class for carnivorous dinosaurs (predators)
65class Carnivore extends Dinosaur {
66 constructor(name, species, age, attackPower) {
67 super(name, species, age, "carnivore");
68 this.attackPower = attackPower;
69 this.huntingSuccess = 0.7; // 70% chance of successful hunt
70 }
71
72 hunt(prey) {
73 if (!this.alive) return `${this.name} is dead, cannot hunt.`;
74 if (!prey.alive) return `${prey.name} is already dead.`;
75
76 const huntSuccess = Math.random() < this.huntingSuccess;
77
78 if (huntSuccess) {
79 const damage = Math.floor(this.attackPower * (0.7 + Math.random() * 0.6));
80 const result = prey.damage(damage);
81 this.eat("meat");
82 return `${this.name} successfully hunts ${prey.name}! ${result}`;
83 } else {
84 return `${this.name} tries to hunt ${prey.name}, but fails.`;
85 }
86 }
87
88 biteAttack(target) {
89 if (!this.alive) return `${this.name} is dead, cannot attack.`;
90 if (!target.alive) return `${target.name} is already dead.`;
91
92 const damage = Math.floor(this.attackPower * 1.2);
93 const result = target.damage(damage);
94 return `${this.name} bites ${target.name}! ${result}`;
95 }
96}
97
98// Class for herbivorous dinosaurs
99class Herbivore extends Dinosaur {
100 constructor(name, species, age, defenseRating) {
101 super(name, species, age, "herbivore");
102 this.defenseRating = defenseRating;
103 this.fleeSuccess = 0.6; // 60% chance of successful escape
104 }
105
106 grazeVegetation() {
107 if (!this.alive) return `${this.name} is dead, cannot eat.`;
108
109 this.health = Math.min(100, this.health + 15);
110 return `${this.name} grazes on plants. Health rises to ${this.health}%.`;
111 }
112
113 flee(predator) {
114 if (!this.alive) return `${this.name} is dead, cannot flee.`;
115
116 const escapeSuccess = Math.random() < this.fleeSuccess;
117
118 if (escapeSuccess) {
119 this.health = Math.max(0, this.health - 5);
120 return `${this.name} successfully flees from ${predator.name}!`;
121 } else {
122 return `${this.name} tries to flee from ${predator.name}, but fails.`;
123 }
124 }
125
126 // Defensive method — reduces incoming damage
127 damage(amount) {
128 const reducedDamage = Math.max(0, amount - this.defenseRating);
129 return super.damage(reducedDamage);
130 }
131}
132
133// Specific dinosaur species
134class Tyrannosaurus extends Carnivore {
135 constructor(name, age) {
136 super(name, "Tyrannosaurus Rex", age, 35);
137 this.intimidationFactor = 9;
138 }
139
140 intimidate(target) {
141 return `${this.name} lets out a deafening roar that terrifies ${target.name}!`;
142 }
143
144 roar() {
145 return `${this.name} lets out a mighty, deafening roar that echoes for miles!`;
146 }
147}
148
149class Velociraptor extends Carnivore {
150 constructor(name, age) {
151 super(name, "Velociraptor", age, 20);
152 this.speed = 70; // km/h
153 this.intelligence = 9;
154 this.packHunting = true;
155 }
156
157 coordinateAttack(targets) {
158 if (!Array.isArray(targets) || targets.length < 2) {
159 return `${this.name} needs at least two targets to coordinate an attack.`;
160 }
161
162 let results = `${this.name} coordinates a pack attack on ${targets.map(t => t.name).join(', ')}!
163`;
164 targets.forEach(target => {
165 const damage = Math.floor(this.attackPower * 1.5);
166 results += target.damage(damage) + '\n';
167 });
168
169 return results;
170 }
171
172 ambush(target) {
173 const damage = Math.floor(this.attackPower * 2);
174 const result = target.damage(damage);
175 return `${this.name} ambushes ${target.name}! ${result}`;
176 }
177}
178
179class Triceratops extends Herbivore {
180 constructor(name, age) {
181 super(name, "Triceratops", age, 25);
182 this.hornStrength = 30;
183 }
184
185 chargeAttack(target) {
186 const damage = this.hornStrength + Math.floor(Math.random() * 10);
187 const result = target.damage(damage);
188 return `${this.name} charges at ${target.name} with its horns! ${result}`;
189 }
190
191 defendFromAttack(attacker) {
192 const counterDamage = Math.floor(this.hornStrength * 0.5);
193 const result = attacker.damage(counterDamage);
194 return `${this.name} defends itself from ${attacker.name} using its horns! ${result}`;
195 }
196}
197
198class Brachiosaurus extends Herbivore {
199 constructor(name, age) {
200 super(name, "Brachiosaurus", age, 15);
201 this.height = 13; // meters
202 this.tailLength = 9; // meters
203 }
204
205 reachHighVegetation() {
206 this.health = Math.min(100, this.health + 20);
207 return `${this.name} reaches up with its long neck to eat leaves from tall trees. Health rises to ${this.health}%.`;
208 }
209
210 tailWhip(target) {
211 const damage = Math.floor(this.tailLength * 2);
212 const result = target.damage(damage);
213 return `${this.name} strikes ${target.name} with its massive tail! ${result}`;
214 }
215}
216
217// Jurassic Park simulation
218function runJurassicParkSimulation() {
219 console.log("=== JURASSIC PARK SIMULATION ===
220");
221
222 // Creating dinosaurs
223 const rex = new Tyrannosaurus("Rex", 8);
224 const blue = new Velociraptor("Blue", 4);
225 const delta = new Velociraptor("Delta", 4);
226 const trixie = new Triceratops("Trixie", 12);
227 const bronty = new Brachiosaurus("Bronty", 25);
228
229 // Display dinosaur info
230 console.log(rex.getStatus());
231 console.log(blue.getStatus());
232 console.log(trixie.getStatus());
233 console.log(bronty.getStatus());
234
235 console.log("
236=== DINOSAUR INTERACTIONS ===
237");
238
239 console.log(rex.roar());
240 console.log(blue.roar());
241 console.log(trixie.grazeVegetation());
242 console.log(bronty.reachHighVegetation());
243
244 console.log("
245=== BATTLE: REX VS TRIXIE ===
246");
247
248 console.log(rex.intimidate(trixie));
249 console.log(trixie.flee(rex));
250 console.log(rex.hunt(trixie));
251 console.log(trixie.defendFromAttack(rex));
252 console.log(rex.biteAttack(trixie));
253
254 console.log("
255=== VELOCIRAPTOR PACK HUNT ===
256");
257
258 console.log(blue.coordinateAttack([trixie, bronty]));
259 console.log(delta.ambush(bronty));
260 console.log(bronty.tailWhip(delta));
261
262 console.log("
263=== DINOSAUR STATUS AFTER INTERACTIONS ===
264");
265
266 console.log(rex.getStatus());
267 console.log(blue.getStatus());
268 console.log(delta.getStatus());
269 console.log(trixie.getStatus());
270 console.log(bronty.getStatus());
271}
272
273// Run the simulation
274runJurassicParkSimulation();Prototypal inheritance in JavaScript differs from classical inheritance in other OOP languages:
Just as Jurassic Park experimented with different cloning methods, the JavaScript world is also evolving, offering new server-side runtimes. Besides Node.js, which has been the de facto standard for years, interesting alternatives have emerged: Deno and Bun.
Deno was created by Ryan Dahl - the same developer who created Node.js! In 2018, during a presentation titled "10 Things I Regret About Node.js," Ryan presented his vision of a better runtime for JavaScript and TypeScript. It's like Dr. Hammond in Jurassic Park, who after initial failures tried to create a more perfect, safer solution.
1. Native TypeScript
Deno supports TypeScript out of the box - no extra configuration or transpilation needed:
1// dinosaur.ts
2interface Dinosaur {
3 name: string;
4 species: string;
5 age: number;
6 dangerous: boolean;
7}
8
9function createDinosaur(name: string, species: string): Dinosaur {
10 return {
11 name,
12 species,
13 age: 0,
14 dangerous: species === "Tyrannosaurus Rex"
15 };
16}
17
18const rex = createDinosaur("Rexy", "Tyrannosaurus Rex");
19console.log(rex);You run it directly:
1deno run dinosaur.ts2. Permission System
Deno's biggest innovation is its permission system. In Node.js, every script has full access to the filesystem, network, and environment variables. Deno requires explicit permissions - like the security systems in Jurassic Park that control access to different zones:
1# No permissions - script can't do anything
2deno run script.ts
3
4# With network access
5deno run --allow-net script.ts
6
7# With file access in a specific directory
8deno run --allow-read=/data --allow-write=/data script.ts
9
10# With environment variable access
11deno run --allow-env script.ts
12
13# All permissions (use carefully!)
14deno run --allow-all script.tsExample with the park security system:
1// security-monitor.ts
2// This script monitors security status and writes logs
3
4// Attempting to read sensors without permissions
5try {
6 const sensors = await fetch("http://park-sensors.internal/status");
7 const data = await sensors.json();
8 console.log("Sensor status:", data);
9} catch (error) {
10 console.error("No network permission:", error.message);
11}
12
13// Attempting to write logs without permissions
14try {
15 await Deno.writeTextFile("./logs/security.log", "System operational
16");
17} catch (error) {
18 console.error("No write permission:", error.message);
19}Running:
1# This will fail — no permissions
2deno run security-monitor.ts
3
4# This will work
5deno run --allow-net --allow-write=./logs security-monitor.ts3. No node_modules
Deno doesn't use
node_modules. Instead, it imports modules directly from URLs and caches them locally:1// Import from URL
2import { serve } from "https://deno.land/std@0.200.0/http/server.ts";
3
4// HTTP server serving dinosaur data
5const handler = (req: Request): Response => {
6 const dinosaurs = [
7 { name: "Rexy", species: "T-Rex" },
8 { name: "Blue", species: "Velociraptor" }
9 ];
10
11 return new Response(JSON.stringify(dinosaurs), {
12 headers: { "content-type": "application/json" }
13 });
14};
15
16serve(handler, { port: 8000 });4. Standard Library
Deno has a well-designed standard library, similar to Go or Python. You don't need to install dozens of packages for basic operations:
1// Working with files
2import { readLines } from "https://deno.land/std@0.200.0/io/mod.ts";
3
4// Reading dinosaur logs line by line
5const file = await Deno.open("dinosaur-logs.txt");
6for await (const line of readLines(file)) {
7 console.log("Log entry:", line);
8}
9file.close();
10
11// Working with UUID
12import { v4 } from "https://deno.land/std@0.200.0/uuid/mod.ts";
13
14const dinosaurId = v4.generate();
15console.log("New dinosaur ID:", dinosaurId);5. Built-in Tools
Deno has built-in tools that would require additional packages in Node.js:
1# Code formatting
2deno fmt script.ts
3
4# Linting
5deno lint script.ts
6
7# Tests
8deno test tests/
9
10# Bundling
11deno bundle main.ts output.js
12
13# Documentation
14deno doc module.tsUse Deno when:
Stick with Node.js when:
Bun is another modern alternative focused on performance. Written in Zig instead of C++ (like Node.js and Deno), it offers impressive speed:
1// Bun supports TypeScript natively
2Bun.serve({
3 port: 3000,
4 fetch(req) {
5 return new Response("Welcome to the Jurassic Park management system!");
6 }
7});1. Blazing Speed
2. Node.js Compatibility
3. Built-in Tools
1# Bundler
2bun build ./index.ts --outdir ./dist
3
4# Test runner
5bun test
6
7# Package manager (super fast!)
8bun install
9bun add lodash4. Built-in SQLite
1import { Database } from "bun:sqlite";
2
3const db = new Database("dinosaurs.db");
4
5// Create table
6db.run(`
7 CREATE TABLE IF NOT EXISTS dinosaurs (
8 id INTEGER PRIMARY KEY,
9 name TEXT,
10 species TEXT,
11 age INTEGER
12 )
13`);
14
15// Insert data
16const insert = db.prepare("INSERT INTO dinosaurs (name, species, age) VALUES (?, ?, ?)");
17insert.run("Rexy", "T-Rex", 8);
18insert.run("Blue", "Velociraptor", 4);
19
20// Queries
21const dinosaurs = db.query("SELECT * FROM dinosaurs").all();
22console.log(dinosaurs);| Feature | Node.js | Deno | Bun | |---------|---------|------|-----| | TypeScript | Requires config | Native | Native | | Package manager | npm/yarn/pnpm | Built-in | Super fast | | Permission system | None | Yes | None | | npm compatibility | 100% | ~Partial | High | | Performance | Standard | Good | Excellent | | Ecosystem | Huge | Growing | Young | | Stability | Production | Stable | Beta/Dev |
Node.js + Express:
1// Requires: npm install express
2const express = require('express');
3const app = express();
4
5app.get('/dinosaurs', (req, res) => {
6 res.json([
7 { name: "Rexy", species: "T-Rex" },
8 { name: "Blue", species: "Velociraptor" }
9 ]);
10});
11
12app.listen(3000, () => console.log('Server running on port 3000'));Deno:
1// No installation needed - everything from URL
2import { serve } from "https://deno.land/std@0.200.0/http/server.ts";
3
4serve((req) => {
5 const dinosaurs = [
6 { name: "Rexy", species: "T-Rex" },
7 { name: "Blue", species: "Velociraptor" }
8 ];
9
10 return new Response(JSON.stringify(dinosaurs), {
11 headers: { "content-type": "application/json" }
12 });
13}, { port: 3000 });
14
15console.log("Server running on port 3000");Bun:
1// Built-in API, super fast
2Bun.serve({
3 port: 3000,
4 fetch(req) {
5 const dinosaurs = [
6 { name: "Rexy", species: "T-Rex" },
7 { name: "Blue", species: "Velociraptor" }
8 ];
9
10 return new Response(JSON.stringify(dinosaurs), {
11 headers: { "content-type": "application/json" }
12 });
13 }
14});
15
16console.log("Server running on port 3000");Just as Jurassic Park experimented with different methods to find the best solutions, the JavaScript world offers various runtimes, each with its own strengths:
The choice depends on your needs, but knowing the alternatives makes you better prepared for the future of JavaScript!
Prototypes and prototypal inheritance are fundamental concepts in JavaScript. Even when using modern class syntax (ES6+), it's important to understand the underlying prototype mechanism to fully leverage the language's capabilities. In our Jurassic Park, prototypal inheritance helps us model different types of dinosaurs and their behaviors in a consistent, efficient way.
The main concepts we covered:
Understanding prototypes and inheritance in JavaScript is key to writing efficient, well-organized code that can model complex relationships between objects, just like those in our virtual Jurassic Park.
"Prototypes and inheritance in JavaScript are like the genetic code in Jurassic Park" - says Dr. Rex. "A Tyrannosaurus inherits traits from Carnivore, which inherits from Dinosaur, which inherits from Creature. Each level adds specialized capabilities. ES6 classes are like modern genetic engineering - the same DNA, but cleaner tools!"