JavaScript and TypeScript course Β· Module 5: Advanced JavaScript

Browser Console and Its Functions

10 min read
In this lesson6

Managing Jurassic Park is no easy task. When problems arise in the dinosaur tracking system or we need to quickly diagnose why the lockdown protocol isn't starting correctly, debugging is a critical skill. One of the most important diagnostic tools in JavaScript is the browser console.

In this exercise we'll learn about a tool that will be your best friend when searching for and solving problems - the browser developer console.

Opening the Developer Console

Before we start using the console, we need to know how to open it:

  • Chrome/Edge: <kbd>F12</kbd> or <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>J</kbd> (Windows/Linux) or <kbd>Cmd</kbd>+<kbd>Option</kbd>+<kbd>J</kbd> (Mac)
  • Firefox: <kbd>F12</kbd> or <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>K</kbd> (Windows/Linux) or <kbd>Cmd</kbd>+<kbd>Option</kbd>+<kbd>K</kbd> (Mac)
  • Safari: <kbd>Cmd</kbd>+<kbd>Option</kbd>+<kbd>C</kbd> (you must first enable developer tools in settings)

After opening you'll see several tabs, including "Console". That's where we'll focus.

Basic Console Functions

1. console.log() - Your Best Friend

The most commonly used console function is console.log(). It displays values in the console, which is indispensable during debugging:

1// Displaying simple values
2console.log("Dinosaur tracking system started");
3console.log(42); // number
4console.log(true); // boolean value
5
6// Displaying multiple values at once
7const dinosaur = { name: "Rex", type: "T-Rex", status: "contained" };
8console.log("Dinosaur data:", dinosaur, "Update:", new Date());
9
10// String interpolation
11const sector = "B7";
12const threat = "high";
13console.log(`Dinosaur detected in sector ${sector}. Threat level: ${threat}`);

In our Jurassic Park system we can use console.log() to track various events:

1function trackDinosaur(id, location) {
2  console.log(`Tracking dinosaur #${id} at location ${location}`);
3
4  // Tracking logic...
5  const status = checkContainment(id);
6
7  if (status !== "contained") {
8    console.log(`ALERT: Dinosaur #${id} is not in its enclosure! Current status: ${status}`);
9  }
10
11  return status;
12}

2. console.error(), console.warn(), console.info()

In addition to the standard log, we have special methods for different message levels:

1// Errors - usually displayed in red
2console.error("CRITICAL ERROR: Fence system failure in T-Rex sector!");
3
4// Warnings - usually displayed in yellow
5console.warn("Warning: Motion sensor battery level dropping below 20%");
6
7// Info - often distinguished from regular logs
8console.info("Info: Technical system review scheduled for tomorrow, 8:00");

Using them helps visually distinguish message types in the console, which is especially important when dealing with large volumes of logs.

3. console.table() - Clean Display of Tabular Data

When dealing with arrays of objects, console.table() is invaluable:

1// Array of dinosaurs in our park
2const dinosaurs = [
3  { id: 1, name: "Rex", species: "T-Rex", danger: 9, location: "Enclosure A" },
4  { id: 2, name: "Blue", species: "Velociraptor", danger: 8, location: "Enclosure B" },
5  { id: 3, name: "Delta", species: "Velociraptor", danger: 8, location: "Enclosure B" },
6  { id: 4, name: "Echo", species: "Velociraptor", danger: 7, location: "Enclosure B" },
7  { id: 5, name: "Trike", species: "Triceratops", danger: 4, location: "Enclosure C" }
8];
9
10// Displays a beautiful table with the data
11console.table(dinosaurs);
12
13// We can also select specific columns
14console.table(dinosaurs, ["name", "species", "danger"]);

This is especially useful for data analysis, checking API query results, or reviewing configurations.

4. console.group() - Grouping Logs

When we have many related logs, we can group them for clarity:

1// Monitoring a specific dinosaur
2function monitorDinosaur(dinosaur) {
3  console.group(`Monitoring: ${dinosaur.name} (${dinosaur.species})`);
4
5  console.log(`Location: ${dinosaur.location}`);
6  console.log(`Danger level: ${dinosaur.danger}/10`);
7
8  const healthStatus = checkHealth(dinosaur.id);
9  console.log(`Health status: ${healthStatus.status}`);
10
11  if (healthStatus.issues.length > 0) {
12    console.warn(`Health issues detected: ${healthStatus.issues.join(', ')}`);
13  }
14
15  const securityStatus = checkSecurity(dinosaur.location);
16  console.log(`Security status: ${securityStatus.status}`);
17
18  if (securityStatus.issues.length > 0) {
19    console.error(`Security issues: ${securityStatus.issues.join(', ')}`);
20  }
21
22  console.groupEnd();
23
24  return { healthStatus, securityStatus };
25}
26
27// Grouping can also be nested
28function monitorAllDinosaurs(dinosaurs) {
29  console.group('Monitoring all dinosaurs');
30
31  dinosaurs.forEach(dino => {
32    monitorDinosaur(dino);
33  });
34
35  console.groupEnd();
36}
37
38monitorAllDinosaurs(dinosaurs);

You can also start a group collapsed using console.groupCollapsed(), which is useful with many groups.

5. console.time() and console.timeEnd() - Measuring Execution Time

Sometimes we need to know how long certain operations take:

1// Measuring module load time
2console.time('Loading tracking module');
3
4loadTrackingModule()
5  .then(() => {
6    console.timeEnd('Loading tracking module');
7    // Displays e.g.: "Loading tracking module: 235.41ms"
8  });
9
10// We can have multiple parallel timers
11console.time('System initialization');
12console.time('Data processing');
13
14initSystem()
15  .then(() => {
16    console.timeEnd('System initialization');
17    return processData();
18  })
19  .then(() => {
20    console.timeEnd('Data processing');
21  });

This is extremely useful for identifying bottlenecks in applications and optimizing performance.

6. console.trace() - Call Stack Tracing

When you don't know exactly where a function was called from:

1function monitorFenceStatus(sectorId) {
2  console.trace(`Checking fence status in sector ${sectorId}`);
3  // Rest of code...
4}
5
6function checkAllFences() {
7  const sectors = ['A1', 'B2', 'C3'];
8  sectors.forEach(monitorFenceStatus);
9}
10
11function dailySecurityCheck() {
12  checkAllFences();
13}
14
15dailySecurityCheck();

console.trace() will display the full call stack, showing the exact execution path, which is invaluable when debugging complex calls.

7. console.assert() - Conditional Debug Messages

Checks a condition and displays an error when the condition is false:

1function feedDinosaur(dinosaur, foodAmount) {
2  // Make sure the food amount is sufficient for the species
3  console.assert(
4    foodAmount >= getMinimumFoodRequirement(dinosaur.species),
5    `Insufficient food for ${dinosaur.name}! ` +
6    `Required minimum: ${getMinimumFoodRequirement(dinosaur.species)}kg, ` +
7    `Provided: ${foodAmount}kg`
8  );
9
10  // Rest of code...
11}
12
13feedDinosaur(dinosaurs[0], 5); // If 5kg is too little, we'll see an error

This is useful for early detection of potential problems without stopping program execution.

8. console.count() - Counting Calls

Counting how many times a function or code block has been called:

1function checkFenceVoltage(sectorId) {
2  console.count(`Voltage check in sector ${sectorId}`);
3  // Rest of code...
4}
5
6// Simulate regular checks
7setInterval(() => checkFenceVoltage('A1'), 5000);
8setInterval(() => checkFenceVoltage('B2'), 8000);

After each call we'll see in the console something like:

1Voltage check in sector A1: 1
2Voltage check in sector A1: 2
3Voltage check in sector B2: 1
4Voltage check in sector A1: 3

We can reset the counter using console.countReset('name').

9. console.dir() - Displaying Object Properties

When we want to see the full structure of an object:

1const parkSystem = {
2  name: "Jurassic Park",
3  sectors: {
4    A: { dinosaurs: [/*...*/], status: "secure" },
5    B: { dinosaurs: [/*...*/], status: "alert" }
6  },
7  security: {
8    fences: { status: "online", voltage: 10000 },
9    cameras: { operational: 45, offline: 3 }
10  }
11};
12
13// Displays an interactive, expandable object structure
14console.dir(parkSystem);

This function is especially useful for complex objects, as it allows browsing nested properties.

10. Console Message Formatting

The console also supports basic formatting with format specifiers:

1// Styling text with CSS
2console.log(
3  "%cWARNING! %cCritical danger level %cin sector B!",
4  "color: red; font-size: 20px; font-weight: bold;",
5  "color: orange; font-size: 16px;",
6  "color: black; font-weight: bold;"
7);
8
9// Displaying variables in a message
10console.log("Dinosaur %s has danger level %d", "Rex", 9);

Advanced Console Features

1. Filtering Messages

Most browser consoles allow filtering displayed messages. We can filter by:

  • Level (Error, Warning, Info, Log)
  • Text (typing a search phrase)
  • Source (e.g. only from a specific file)

This is extremely useful when dealing with large volumes of logs.

2. Saving to File

Console messages can usually be saved to a file, which is useful for log analysis:

  1. Right-click in the console
  2. Select "Save as..."

3. Clearing the Console

The console can be cleared in several ways:

  • Clicking the crossed-circle icon in the console
  • Pressing <kbd>Ctrl</kbd>+<kbd>L</kbd> (when the console is active)
  • Using code: console.clear()

4. Console as a REPL Environment

The browser console also works as a REPL (Read-Eval-Print Loop), meaning we can execute JavaScript code directly in it:

1// Directly in console
2const dinos = [{name: "Rex"}, {name: "Blue"}];
3dinos.filter(d => d.name === "Blue");
4
5// Defining functions
6function alertSecurity(message) {
7  return `[SECURITY ALERT] ${message} - ${new Date().toISOString()}`;
8}
9
10// Using the function
11alertSecurity("Fence breach in sector C2");

This is extremely useful for testing small code snippets or debugging without modifying source code.

Practical Implementation in Our Jurassic Park System

Let's create a practical implementation of a logging system for our Jurassic Park that makes use of various console functions:

1// Logger for the Jurassic Park system
2class JurassicLogger {
3  constructor(moduleName) {
4    this.moduleName = moduleName;
5    this.logCount = 0;
6    this.errorCount = 0;
7    this.warnCount = 0;
8  }
9
10  log(...args) {
11    this.logCount++;
12    console.log(`[${this.moduleName}] `, ...args);
13  }
14
15  error(...args) {
16    this.errorCount++;
17    console.error(`[${this.moduleName}] ERROR:`, ...args);
18  }
19
20  warn(...args) {
21    this.warnCount++;
22    console.warn(`[${this.moduleName}] WARNING:`, ...args);
23  }
24
25  info(...args) {
26    console.info(`[${this.moduleName}] INFO:`, ...args);
27  }
28
29  startGroup(label) {
30    console.group(`[${this.moduleName}] ${label}`);
31  }
32
33  endGroup() {
34    console.groupEnd();
35  }
36
37  startTimer(label) {
38    console.time(`[${this.moduleName}] ${label}`);
39  }
40
41  endTimer(label) {
42    console.timeEnd(`[${this.moduleName}] ${label}`);
43  }
44
45  table(data, columns) {
46    console.log(`[${this.moduleName}] Tabular data:`);
47    console.table(data, columns);
48  }
49
50  getStats() {
51    return {
52      moduleName: this.moduleName,
53      logs: this.logCount,
54      errors: this.errorCount,
55      warnings: this.warnCount
56    };
57  }
58
59  trace(message) {
60    console.log(`[${this.moduleName}] TRACE: ${message}`);
61    console.trace();
62  }
63
64  assert(condition, message) {
65    console.assert(condition, `[${this.moduleName}] Assertion failed: ${message}`);
66  }
67
68  // Special formatting for security alerts
69  securityAlert(message, level = 'warning') {
70    const styles = {
71      warning: "background: #FFA500; color: black; padding: 2px 5px; border-radius: 3px;",
72      critical: "background: #FF0000; color: white; padding: 2px 5px; border-radius: 3px; font-weight: bold;",
73      info: "background: #0066FF; color: white; padding: 2px 5px; border-radius: 3px;"
74    };
75
76    console.log(
77      `%c[${this.moduleName}] SECURITY ALERT %c${message}`,
78      styles[level] || styles.warning,
79      "color: black;"
80    );
81  }
82}
83
84// Example usage
85const securityLogger = new JurassicLogger('ParkSecurity');
86const dinosaurLogger = new JurassicLogger('DinosaurTracker');
87const systemLogger = new JurassicLogger('MainSystem');
88
89// System initialization
90systemLogger.startTimer('System initialization');
91systemLogger.log('Starting Jurassic Park system initialization...');
92
93setTimeout(() => {
94  systemLogger.info('Subsystems started');
95  systemLogger.endTimer('System initialization');
96
97  // Dinosaur information
98  const dinoData = [
99    { id: 'TRX-01', name: 'Rex', species: 'T-Rex', status: 'contained', healthLevel: 92 },
100    { id: 'VEL-01', name: 'Blue', species: 'Velociraptor', status: 'contained', healthLevel: 87 },
101    { id: 'VEL-02', name: 'Delta', species: 'Velociraptor', status: 'sedated', healthLevel: 65 },
102    { id: 'TRI-01', name: 'Sarah', species: 'Triceratops', status: 'contained', healthLevel: 95 }
103  ];
104
105  dinosaurLogger.startGroup('Dinosaur status report');
106  dinosaurLogger.table(dinoData);
107
108  // Check dinosaur health
109  dinoData.forEach(dino => {
110    dinosaurLogger.startGroup(`Dinosaur: ${dino.name}`);
111
112    if (dino.healthLevel < 70) {
113      dinosaurLogger.warn(`Dinosaur ${dino.name} health level is low: ${dino.healthLevel}%`);
114    } else {
115      dinosaurLogger.log(`Health status: ${dino.healthLevel}%`);
116    }
117
118    if (dino.status !== 'contained') {
119      dinosaurLogger.error(`Dinosaur ${dino.name} is not in its enclosure! Status: ${dino.status}`);
120      securityLogger.securityAlert(`Dinosaur ${dino.name} (${dino.species}) status: ${dino.status}`, 'critical');
121    }
122
123    dinosaurLogger.endGroup();
124  });
125
126  dinosaurLogger.endGroup();
127
128  // Check security systems
129  securityLogger.startGroup('Security systems');
130
131  const fenceStatus = { sector: 'B', voltage: 9800, status: 'active' };
132  securityLogger.log(`Fence status in sector ${fenceStatus.sector}: ${fenceStatus.status}`);
133  securityLogger.assert(
134    fenceStatus.voltage >= 10000,
135    `Fence voltage in sector ${fenceStatus.sector} is too low: ${fenceStatus.voltage}V (min. 10000V)`
136  );
137
138  securityLogger.endGroup();
139
140  // Display log stats
141  systemLogger.startGroup('Log statistics');
142  console.table([
143    securityLogger.getStats(),
144    dinosaurLogger.getStats(),
145    systemLogger.getStats()
146  ]);
147  systemLogger.endGroup();
148
149}, 2000);

Production and Development Logging

In real applications it's worth separating development logging from production logging:

1// logger.js
2class Logger {
3  constructor(isProduction = process.env.NODE_ENV === 'production') {
4    this.isProduction = isProduction;
5  }
6
7  log(...args) {
8    if (!this.isProduction) {
9      console.log(...args);
10    }
11  }
12
13  // For critical errors, we log even in production
14  error(...args) {
15    console.error(...args);
16
17    if (this.isProduction) {
18      // In production we can send errors to a monitoring service
19      this.sendToErrorMonitoring(args);
20    }
21  }
22
23  sendToErrorMonitoring(errorData) {
24    // Implementation for sending to Sentry, LogRocket, etc.
25  }
26}
27
28export default new Logger();

Summary

The browser console is a powerful tool that greatly simplifies debugging and monitoring JavaScript applications. In the context of our Jurassic Park, good logging practices can be the difference between a smoothly running park and... well, the scenario from the movies!

Key functions to remember:

  • console.log() - basic logging
  • console.error(), console.warn(), console.info() - different message levels
  • console.table() - clean data display
  • console.group() - organizing related logs
  • console.time() and console.timeEnd() - measuring performance
  • console.trace() - diagnosing where a call comes from
  • console.assert() - conditional debug messages

Remember to regularly use the console during development - it will help you detect and fix bugs faster, before the dinosaurs find a hole in your code!

Code for this lesson: main.js
1// Re-exporting and module aggregation - Jurassic Park
2// Creating "index" modules for easier importing
3
4console.log("Re-exporting and Module Aggregation");
5console.log("Module structure organization\n");
6
7// ===========================================
8// BASE MODULES
9// ===========================================
10
11// === types/DinosaurTypes.js ===
12const DinosaurTypes = {
13  CARNIVORE: 'carnivore',
14  HERBIVORE: 'herbivore',
15  OMNIVORE: 'omnivore'
16};
17
18const DangerLevels = {
19  LOW: 1,
20  MEDIUM: 5,
21  HIGH: 7,
22  CRITICAL: 9
23};
24
25// === models/Dinosaur.js ===
26class Dinosaur {
27  constructor(name, species, type, dangerLevel) {
28    this.name = name;
29    this.species = species;
30    this.type = type;
31    this.dangerLevel = dangerLevel;
32    this.health = 100;
33    this.id = Math.random().toString(36).substr(2, 9);
34  }
35
36  getInfo() {
37    return `${this.name} (${this.species}) - Danger: ${this.dangerLevel}/10`;
38  }
39}
40
41// === models/Enclosure.js ===
42class Enclosure {
43  constructor(id, name, capacity) {
44    this.id = id;
45    this.name = name;
46    this.capacity = capacity;
47    this.dinosaurs = [];
48  }
49
50  addDinosaur(dinosaur) {
51    if (this.dinosaurs.length >= this.capacity) {
52      throw new Error('Enclosure is full');
53    }
54    this.dinosaurs.push(dinosaur);
55  }
56
57  getStatus() {
58    return `${this.name}: ${this.dinosaurs.length}/${this.capacity} dinosaurs`;
59  }
60}
61
62// === models/Visitor.js ===
63class Visitor {
64  constructor(name, age, ticketType) {
65    this.name = name;
66    this.age = age;
67    this.ticketType = ticketType;
68    this.id = Math.random().toString(36).substr(2, 9);
69  }
70
71  getDetails() {
72    return `${this.name}, ${this.age} years old (${this.ticketType} ticket)`;
73  }
74}
75
76// === utils/validators.js ===
77function validateDinosaur(data) {
78  const { name, species, type, dangerLevel } = data;
79  const errors = [];
80
81  if (!name || typeof name !== 'string') errors.push('Invalid name');
82  if (!species || typeof species !== 'string') errors.push('Invalid species');
83  if (!Object.values(DinosaurTypes).includes(type)) errors.push('Invalid type');
84  if (dangerLevel < 1 || dangerLevel > 10) errors.push('Danger level must be 1-10');
85
86  return { valid: errors.length === 0, errors };
87}
88
89function validateEnclosure(data) {
90  const { id, name, capacity } = data;
91  const errors = [];
92
93  if (!id || typeof id !== 'string') errors.push('Invalid id');
94  if (!name || typeof name !== 'string') errors.push('Invalid name');
95  if (!capacity || capacity < 1) errors.push('Capacity must be at least 1');
96
97  return { valid: errors.length === 0, errors };
98}
99
100// === utils/formatters.js ===
101function formatDinosaurReport(dinosaur) {
102  return {
103    id: dinosaur.id,
104    name: dinosaur.name,
105    species: dinosaur.species,
106    type: dinosaur.type,
107    dangerLevel: dinosaur.dangerLevel,
108    health: `${dinosaur.health}%`,
109    status: dinosaur.health > 70 ? 'Good' : 'Needs attention'
110  };
111}
112
113function formatEnclosureReport(enclosure) {
114  return {
115    id: enclosure.id,
116    name: enclosure.name,
117    occupancy: `${enclosure.dinosaurs.length}/${enclosure.capacity}`,
118    dinosaurs: enclosure.dinosaurs.map(d => d.name),
119    status: enclosure.dinosaurs.length >= enclosure.capacity ? 'Full' : 'Available'
120  };
121}
122
123// ===========================================
124// AGGREGATING MODULES (BARREL EXPORTS)
125// ===========================================
126
127// === models/index.js - Aggregating all models ===
128// Re-exporting all models from one place
129const ModelsModule = {
130  Dinosaur,
131  Enclosure,
132  Visitor
133};
134
135console.log("Models Module:");
136console.log("  - Dinosaur");
137console.log("  - Enclosure");
138console.log("  - Visitor\n");
139
140// === types/index.js - Type aggregation ===
141const TypesModule = {
142  DinosaurTypes,
143  DangerLevels
144};
145
146console.log("Types Module:");
147console.log("  - DinosaurTypes");
148console.log("  - DangerLevels\n");
149
150// === utils/index.js - Aggregating utilities ===
151const UtilsModule = {
152  // validators
153  validateDinosaur,
154  validateEnclosure,
155  // formatters
156  formatDinosaurReport,
157  formatEnclosureReport
158};
159
160console.log("Utils Module:");
161console.log("  - validateDinosaur");
162console.log("  - validateEnclosure");
163console.log("  - formatDinosaurReport");
164console.log("  - formatEnclosureReport\n");
165
166// === index.js - MAIN AGGREGATING MODULE ===
167// Re-export everything from submodules
168const JurassicParkSDK = {
169  // Models
170  ...ModelsModule,
171  // Types
172  ...TypesModule,
173  // Utils
174  ...UtilsModule
175};
176
177console.log("Main SDK Module (All exports):");
178console.log("  All models");
179console.log("  All types");
180console.log("  All utilities\n");
181
182// ===========================================
183// USAGE DEMONSTRATION
184// ===========================================
185
186console.log("=== RE-EXPORTING DEMO ===\n");
187
188// Instead of importing from many places:
189console.log("WITHOUT re-exports (many imports):");
190console.log("import { Dinosaur } from './models/Dinosaur.js';");
191console.log("import { Enclosure } from './models/Enclosure.js';");
192console.log("import { DinosaurTypes } from './types/DinosaurTypes.js';");
193console.log("import { validateDinosaur } from './utils/validators.js';");
194console.log("import { formatDinosaurReport } from './utils/formatters.js';\n");
195
196// We can import everything from one place:
197console.log("WITH re-exports (one import):");
198console.log("import {");
199console.log("  Dinosaur, Enclosure,");
200console.log("  DinosaurTypes,");
201console.log("  validateDinosaur, formatDinosaurReport");
202console.log("} from './index.js';\n");
203
204console.log("=== PRACTICAL USAGE ===\n");
205
206// Creating a dinosaur
207const dinoData = {
208  name: 'Rexy',
209  species: 'Tyrannosaurus Rex',
210  type: JurassicParkSDK.DinosaurTypes.CARNIVORE,
211  dangerLevel: JurassicParkSDK.DangerLevels.CRITICAL
212};
213
214console.log("1. Validating the dinosaur data:");
215const validation = JurassicParkSDK.validateDinosaur(dinoData);
216console.log(`   Valid: ${validation.valid}`);
217
218if (validation.valid) {
219  const trex = new JurassicParkSDK.Dinosaur(
220    dinoData.name,
221    dinoData.species,
222    dinoData.type,
223    dinoData.dangerLevel
224  );
225
226  console.log(`\n2. Dinosaur created: ${trex.getInfo()}`);
227
228  const report = JurassicParkSDK.formatDinosaurReport(trex);
229  console.log("\n3. Dinosaur report:");
230  console.log(JSON.stringify(report, null, 2));
231}
232
233// Creating paddock
234console.log("\n4. Creating paddock:");
235const enclosureData = {
236  id: 'ENC-001',
237  name: 'T-Rex Paddock',
238  capacity: 2
239};
240
241const encValidation = JurassicParkSDK.validateEnclosure(enclosureData);
242console.log(`   Valid: ${encValidation.valid}`);
243
244if (encValidation.valid) {
245  const paddock = new JurassicParkSDK.Enclosure(
246    enclosureData.id,
247    enclosureData.name,
248    enclosureData.capacity
249  );
250
251  const trex = new JurassicParkSDK.Dinosaur(
252    'Rexy',
253    'T-Rex',
254    JurassicParkSDK.DinosaurTypes.CARNIVORE,
255    9
256  );
257
258  paddock.addDinosaur(trex);
259
260  const encReport = JurassicParkSDK.formatEnclosureReport(paddock);
261  console.log("\n5. Paddock report:");
262  console.log(JSON.stringify(encReport, null, 2));
263}
264
265console.log("\n=== BENEFITS OF RE-EXPORTING ===\n");
266
267console.log("Simpler imports:");
268console.log("   - One import instead of many");
269console.log("   - Cleaner code\n");
270
271console.log("Better DX (Developer Experience):");
272console.log("   - Easier API discovery");
273console.log("   - Intuitive structure\n");
274
275console.log("Easier refactoring:");
276console.log("   - Changes to the internal structure don't affect users");
277console.log("   - The public API stays stable\n");
278
279console.log("Tree Shaking:");
280console.log("   - Bundlers can remove unused code");
281console.log("   - Smaller bundle size\n");
282
283console.log("=== EXAMPLE PATTERNS ===\n");
284
285console.log("// Basic re-export");
286console.log("export { Dinosaur } from './Dinosaur.js';\n");
287
288console.log("// Re-export with an alias");
289console.log("export { Dinosaur as Dino } from './Dinosaur.js';\n");
290
291console.log("// Re-export everything");
292console.log("export * from './models.js';\n");
293
294console.log("// Re-export with aggregation");
295console.log("export { Dinosaur } from './Dinosaur.js';");
296console.log("export { Enclosure } from './Enclosure.js';");
297console.log("export { Visitor } from './Visitor.js';\n");
298
299console.log("// Mixed export (default + named)");
300console.log("export { default as Dinosaur, DinosaurTypes } from './Dinosaur.js';\n");
301
302console.log("Demo completed!");

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. Which browser tool allows you to measure the execution time of a JavaScript code snippet?

Useful articles