JavaScript and TypeScript course Β· Module 1: JavaScript Basics
Functions
In this lesson16
In Jurassic Park, the team of employees performs various specialized tasks: Dr. Wu handles genetics, the security team monitors fences, and veterinarians take care of dinosaur health. Each specialist performs specific tasks when asked, without needing to explain every time exactly how to do it.
In JavaScript, functions work similarly - they are blocks of code designed to perform specific tasks. Functions can be defined once and called multiple times, making code more modular, readable, and easier to maintain.
Defining Functions
In JavaScript, there are several ways to define functions. Let's start with the most basic one - function declaration:
1// Basic function declaration syntax
2function functionName(parameter1, parameter2, ...) {
3 // Code block to execute
4 return value; // Optional statement returning a value
5}In the context of Jurassic Park, we could create a function to check enclosure safety:
1// Function to check enclosure safety
2function checkEnclosureSafety(powerLevel, fenceCondition, dinoSpecies) {
3 // Safety conditions dependent on species
4 let minPowerLevel;
5
6 if (dinoSpecies === "Tyrannosaurus" || dinoSpecies === "Velociraptor") {
7 minPowerLevel = 90; // For dangerous predators we require high power level
8 } else if (dinoSpecies === "Dilophosaurus" || dinoSpecies === "Carnotaurus") {
9 minPowerLevel = 75; // For smaller predators
10 } else {
11 minPowerLevel = 50; // For herbivores
12 }
13
14 // Check safety conditions
15 if (powerLevel < minPowerLevel) {
16 return "UNSAFE: Power level too low for this species!";
17 }
18
19 if (fenceCondition !== "intact") {
20 return "UNSAFE: Fence requires repair!";
21 }
22
23 return "SAFE: Enclosure meets all safety requirements.";
24}
25
26// Examples of function usage
27let tRexInspectionResult = checkEnclosureSafety(85, "intact", "Tyrannosaurus");
28console.log(`T-Rex enclosure: ${tRexInspectionResult}`); // "T-Rex enclosure: UNSAFE: Power level too low for this species!"
29
30let triceratopsInspectionResult = checkEnclosureSafety(60, "intact", "Triceratops");
31console.log(`Triceratops enclosure: ${triceratopsInspectionResult}`); // "Triceratops enclosure: SAFE: Enclosure meets all safety requirements."Function Expressions
Another way to define functions is using a function expression, where a function is assigned to a variable:
1// Function expression
2const functionName = function(parameter1, parameter2, ...) {
3 // Code block to execute
4 return value; // Optional
5};Example from Jurassic Park:
1// Function to calculate daily food requirement
2const calculateDailyFoodRequirement = function(species, weight, age) {
3 let baseFactor;
4
5 // Determining the base factor depending on diet
6 if (["Tyrannosaurus", "Velociraptor", "Spinosaurus"].includes(species)) {
7 baseFactor = 0.10; // 10% of body weight for carnivores
8 } else if (["Allosaurus", "Carnotaurus", "Dilophosaurus"].includes(species)) {
9 baseFactor = 0.08; // 8% of body weight for smaller carnivores
10 } else {
11 baseFactor = 0.15; // 15% of body weight for herbivores (eat more, but less caloric food)
12 }
13
14 // Age correction (young specimens eat proportionally more)
15 let ageFactor = age < 5 ? 1.5 : age < 10 ? 1.2 : 1.0;
16
17 // Calculate daily food requirement in kg
18 let dailyRequirement = weight * baseFactor * ageFactor;
19
20 return Math.round(dailyRequirement * 10) / 10; // Round to 1 decimal place
21};
22
23// Usage examples
24console.log(`Daily food requirement for young T-Rex: ${calculateDailyFoodRequirement("Tyrannosaurus", 2000, 3)} kg`);
25// "Daily food requirement for young T-Rex: 300 kg"
26
27console.log(`Daily food requirement for adult Stegosaurus: ${calculateDailyFoodRequirement("Stegosaurus", 5000, 12)} kg`);
28// "Daily food requirement for adult Stegosaurus: 750 kg"Arrow Functions
Arrow functions are a more concise way to write functions, introduced in ES6:
1// Arrow function syntax
2const functionName = (parameter1, parameter2, ...) => {
3 // Code block
4 return value;
5};
6
7// For simple functions with a single expression, you can omit curly braces and the return keyword
8const simpleSum = (a, b) => a + b;Example application in Jurassic Park:
1// Arrow function to classify dinosaurs
2const classifyDinosaur = (species, length, speed) => {
3 // Threat classification based on species, size, and speed
4 if (["Tyrannosaurus", "Spinosaurus"].includes(species) && length > 10) {
5 return "Highest threat - Class A";
6 } else if (["Velociraptor", "Dilophosaurus"].includes(species) && speed > 30) {
7 return "High threat - Class B";
8 } else if (["Allosaurus", "Carnotaurus"].includes(species)) {
9 return "Medium threat - Class C";
10 } else if (species.includes("raptor") || speed > 40) {
11 return "Elevated threat - Class D";
12 } else {
13 return "Low threat - Class E";
14 }
15};
16
17// Simple arrow functions without code blocks
18const isPredator = species => ["Tyrannosaurus", "Velociraptor", "Spinosaurus", "Allosaurus", "Carnotaurus", "Dilophosaurus"].includes(species);
19const estimateSpeed = (limbLength, mass) => Math.round(limbLength * 0.7 * (100 / mass));
20
21// Usage examples
22console.log(classifyDinosaur("Tyrannosaurus", 12, 27)); // "Highest threat - Class A"
23console.log(classifyDinosaur("Gallimimus", 2, 45)); // "Elevated threat - Class D"
24console.log(isPredator("Stegosaurus")); // false
25console.log(estimateSpeed(2.5, 20)); // 9Function Parameters
Functions can accept parameters, which are local variables available inside the function:
Default Parameters
Since ES6, we can define default values for parameters:
1function setIncubatorTemperature(species, temperature = 37.5) {
2 console.log(`Set incubator temperature for ${species} eggs to ${temperature}Β°C`);
3 // Further code...
4}
5
6setIncubatorTemperature("Velociraptor"); // "Set incubator temperature for Velociraptor eggs to 37.5Β°C"
7setIncubatorTemperature("Triceratops", 36.2); // "Set incubator temperature for Triceratops eggs to 36.2Β°C"Rest Parameters
Allow passing an indefinite number of arguments as an array:
1function monitorDinosaurs(...ids) {
2 console.log(`Monitoring ${ids.length} dinosaurs...`);
3
4 for (let id of ids) {
5 console.log(`Checking dinosaur #${id}...`);
6 // Monitoring code...
7 }
8
9 return `Monitoring of ${ids.length} dinosaurs complete.`;
10}
11
12console.log(monitorDinosaurs(101, 102, 103, 104, 105));
13// Will display:
14// "Monitoring 5 dinosaurs..."
15// "Checking dinosaur #101..."
16// "Checking dinosaur #102..."
17// "Checking dinosaur #103..."
18// "Checking dinosaur #104..."
19// "Checking dinosaur #105..."
20// "Monitoring of 5 dinosaurs complete."Returning Values
Functions can return values using the return statement:
1function analyzeDnaSample(sample) {
2 // Sample analysis code...
3
4 if (!sample || sample.length < 10) {
5 return { success: false, message: "Insufficient genetic material." };
6 }
7
8 // Analysis simulation
9 const species = ["Tyrannosaurus", "Triceratops", "Velociraptor", "Stegosaurus", "Brontosaurus"];
10 const randomIndex = Math.floor(Math.random() * species.length);
11
12 return {
13 success: true,
14 species: species[randomIndex],
15 dnaPurity: Math.round(Math.random() * 50 + 50), // 50-100%
16 completeness: Math.round(Math.random() * 40 + 60), // 60-100%
17 message: "Analysis completed successfully."
18 };
19}
20
21const analysisResult = analyzeDnaSample("ACGTAAGTCCTGAT");
22console.log(analysisResult);
23// Example output:
24// {
25// success: true,
26// species: "Velociraptor",
27// dnaPurity: 87,
28// completeness: 75,
29// message: "Analysis completed successfully."
30// }
31
32if (analysisResult.success) {
33 console.log(`Identified ${analysisResult.species} DNA with ${analysisResult.dnaPurity}% purity`);
34} else {
35 console.log(`Analysis error: ${analysisResult.message}`);
36}Variable Scope
Variables defined inside a function are local to that function and are not accessible from outside:
1function prepareJurassicIncident() {
2 // Local variable, not accessible outside the function
3 let secretSystemCode = "TRex1993";
4 console.log(`Code generated inside function: ${secretSystemCode}`);
5 return "Incident prepared.";
6}
7
8prepareJurassicIncident();
9// Attempting to access the local variable outside the function will cause an error
10// console.log(secretSystemCode); // ReferenceError: secretSystemCode is not defined
11
12// Variables defined outside a function are accessible inside
13let jurassicParkLocation = "Isla Nublar";
14
15function displayParkInfo() {
16 // Access to outer variable
17 console.log(`Jurassic Park is located on the island: ${jurassicParkLocation}`);
18
19 // Local variable
20 let dinosaurCount = 200;
21 console.log(`Current dinosaur count: ${dinosaurCount}`);
22}
23
24displayParkInfo();
25// console.log(dinosaurCount); // ReferenceError: dinosaurCount is not definedNested Functions
Functions can be defined inside other functions:
1function conductScientificResearch(species) {
2 console.log(`Starting scientific research on species: ${species}`);
3
4 // Nested function - only accessible inside conductScientificResearch
5 function analyzeSample() {
6 console.log(`Analyzing ${species} DNA sample...`);
7 return "Analysis complete";
8 }
9
10 // Another nested function
11 function simulateGrowth() {
12 console.log(`Simulating ${species} growth and development...`);
13 return "Simulation complete";
14 }
15
16 // Calling nested functions
17 const analysisResult = analyzeSample();
18 const simulationResult = simulateGrowth();
19
20 return {
21 species,
22 analysisResult,
23 simulationResult,
24 researchDate: new Date().toISOString()
25 };
26}
27
28const researchReport = conductScientificResearch("Velociraptor");
29console.log(researchReport);
30// Nested functions are not accessible outside the outer function
31// analyzeSample(); // ReferenceError: analyzeSample is not definedHigher-Order Functions
In JavaScript, functions are first-class objects, which means they can be passed as arguments to other functions or returned by functions:
1// Function accepting another function as a parameter
2function monitorEnclosure(enclosureId, alarmFunction) {
3 console.log(`Monitoring enclosure #${enclosureId}`);
4
5 // Simulating a problem
6 const anomalyDetected = Math.random() > 0.7;
7
8 if (anomalyDetected) {
9 // Calling the passed function when a problem is detected
10 alarmFunction(`Anomaly detected in enclosure #${enclosureId}!`);
11 }
12
13 return { enclosureId, status: anomalyDetected ? "Anomaly" : "Normal" };
14}
15
16// Functions that can be passed as arguments
17function soundAlarm(message) {
18 console.log(`SOUND ALARM: ${message}`);
19}
20
21function visualAlarm(message) {
22 console.log(`VISUAL ALARM: ${message}`);
23}
24
25function staffNotifications(message) {
26 console.log(`SMS NOTIFICATION: ${message}`);
27}
28
29// Using the higher-order function with different alarm functions
30monitorEnclosure(1, soundAlarm);
31monitorEnclosure(2, visualAlarm);
32monitorEnclosure(3, staffNotifications);
33
34// We can also pass an anonymous function
35monitorEnclosure(4, function(message) {
36 console.log(`EMERGENCY PROCEDURE: ${message}`);
37 console.log("Launching evacuation protocol...");
38});
39
40// Or an arrow function
41monitorEnclosure(5, message => console.log(`DIAGNOSTIC REPORT: ${message}`));Function Returning a Function
1// Function creating and returning another function
2function createSpeciesMonitor(species) {
3 // We return a new function tailored to a specific species
4 return function(action) {
5 const actionTime = new Date().toLocaleTimeString();
6 console.log(`[${actionTime}] ${species}: ${action}`);
7
8 // Additional logic dependent on species
9 if (["Tyrannosaurus", "Velociraptor", "Dilophosaurus"].includes(species) && action.includes("near the fence")) {
10 console.log(`WARNING! Dangerous predator ${species} near the fence!`);
11 }
12 };
13}
14
15// Creating monitors for different species
16const tRexMonitor = createSpeciesMonitor("Tyrannosaurus");
17const triceratopsMonitor = createSpeciesMonitor("Triceratops");
18
19// Using the returned functions
20tRexMonitor("Moving in the southern direction");
21tRexMonitor("Approaching near the fence");
22triceratopsMonitor("Grazing in the northern part of the enclosure");Immediately Invoked Function Expressions (IIFE)
An IIFE (Immediately Invoked Function Expression) is a function that is defined and called immediately:
1// IIFE structure
2(function() {
3 // Function code...
4})();
5
6// IIFE with parameters
7(function(name) {
8 console.log(`System initialization: ${name}`);
9})("Jurassic Park");IIFEs are useful for creating a private scope and avoiding pollution of the global object:
1// Jurassic Park system initialization using IIFE
2const jurassicParkSystem = (function() {
3 // Private variables, not accessible from outside
4 const securityCodes = {
5 mainGates: "GATES1993",
6 laboratory: "INGEN2015",
7 powerSystem: "NEDRY1992"
8 };
9
10 let systemStatus = "offline";
11 let securityLevel = 0;
12
13 // Private functions
14 function validateCode(providedCode, requiredCode) {
15 return providedCode === requiredCode;
16 }
17
18 // Public interface - only these functions will be accessible from outside
19 return {
20 startSystem: function() {
21 systemStatus = "online";
22 securityLevel = 3;
23 console.log("Jurassic Park system started.");
24 return true;
25 },
26
27 checkStatus: function() {
28 return {
29 status: systemStatus,
30 securityLevel,
31 updateTime: new Date().toISOString()
32 };
33 },
34
35 grantAccess: function(area, code) {
36 if (!validateCode(code, securityCodes[area])) {
37 console.log(`Access denied to area: ${area}`);
38 return false;
39 }
40 console.log(`Access granted to area: ${area}`);
41 return true;
42 }
43 };
44})();
45
46// Using the public interface
47jurassicParkSystem.startSystem();
48console.log(jurassicParkSystem.checkStatus());
49jurassicParkSystem.grantAccess("mainGates", "GATES1993"); // true
50jurassicParkSystem.grantAccess("laboratory", "wrong code"); // false
51
52// Attempting to access private variables will fail
53// console.log(jurassicParkSystem.securityCodes); // undefined
54// console.log(jurassicParkSystem.validateCode); // undefinedRecursion
Recursion is a technique where a function calls itself:
1// Recursive function simulating dinosaur reproduction
2function simulateReproduction(initialPopulation, yearsAhead, growthRate = 1.5) {
3 // Recursion termination condition
4 if (yearsAhead <= 0) {
5 return initialPopulation;
6 }
7
8 // Calculate new population after one year
9 const newPopulation = Math.round(initialPopulation * growthRate);
10
11 console.log(`Year ${yearsAhead} until end of simulation. Population: ${newPopulation}`);
12
13 // Recursive call with new population and decreased year counter
14 return simulateReproduction(newPopulation, yearsAhead - 1, growthRate);
15}
16
17// Initial population: 2 dinosaurs, simulation for 5 years ahead
18const finalPopulation = simulateReproduction(2, 5);
19console.log(`Final population after 5 years: ${finalPopulation}`);
20
21// Result:
22// Year 5 until end of simulation. Population: 3
23// Year 4 until end of simulation. Population: 5
24// Year 3 until end of simulation. Population: 8
25// Year 2 until end of simulation. Population: 12
26// Year 1 until end of simulation. Population: 18
27// Final population after 5 years: 18It's important to always have a recursion termination condition to avoid infinite calls, which can cause a stack overflow error.
Hoisting
Hoisting is a JavaScript behavior that "moves" declarations to the top of their scope:
1// We can call a function before its declaration thanks to hoisting
2console.log(checkParkSafety()); // "Park safe"
3
4// The function declaration is moved to the top
5function checkParkSafety() {
6 return "Park safe";
7}
8
9// However, function expressions are not fully hoisted
10// console.log(calculateRisk()); // Error: calculateRisk is not a function
11
12// Only the variable declaration is hoisted, not its value
13var calculateRisk = function() {
14 return "Low risk";
15};
16
17// Similarly with let and const - they are hoisted but not initialized
18// console.log(analyzeData); // ReferenceError: Cannot access 'analyzeData' before initialization
19let analyzeData = function() {
20 return "Analysis complete";
21};Closures
A closure is created when an inner function has access to the scope of the outer function, even after it has finished executing:
1function createDinosaurCounter(roomName) {
2 let dinosaurCount = 0;
3
4 // The inner function creates a closure
5 function updateCounter(change) {
6 dinosaurCount += change;
7 console.log(`${roomName}: Current dinosaur count: ${dinosaurCount}`);
8 return dinosaurCount;
9 }
10
11 return {
12 addDinosaur: function() {
13 return updateCounter(1);
14 },
15 removeDinosaur: function() {
16 return updateCounter(-1);
17 },
18 getDinosaurCount: function() {
19 return dinosaurCount;
20 }
21 };
22}
23
24// Creating two independent counters for different rooms
25const enclosureACounter = createDinosaurCounter("Enclosure A");
26const enclosureBCounter = createDinosaurCounter("Enclosure B");
27
28enclosureACounter.addDinosaur(); // "Enclosure A: Current dinosaur count: 1"
29enclosureACounter.addDinosaur(); // "Enclosure A: Current dinosaur count: 2"
30enclosureBCounter.addDinosaur(); // "Enclosure B: Current dinosaur count: 1"
31enclosureACounter.removeDinosaur(); // "Enclosure A: Current dinosaur count: 1"Closures are extremely useful for creating factory functions, data encapsulation, and implementing design patterns.
Best Practices When Using Functions
One function, one task: Functions should be designed to perform one specific task. This makes testing, debugging, and maintaining code easier.
Descriptive function names: Use clear, descriptive function names that indicate their purpose (e.g.,
loginUserinstead ofuFunc1).Limit the number of parameters: Try to limit the number of parameters. If a function requires many parameters, consider using an options object:
1// Instead of:
2function configureSecuritySystem(powerLevel, sensorSensitivity, reactionTime, operationMode, notifications) {
3 //
4}
5
6// Use:
7function configureSecuritySystem(options) {
8 const {
9 powerLevel = 100,
10 sensorSensitivity = "high",
11 reactionTime = 5,
12 operationMode = "automatic",
13 notifications = true
14 } = options;
15
16 //
17}
18
19// Calling:
20configureSecuritySystem({
21 powerLevel: 90,
22 reactionTime: 3,
23 operationMode: "manual"
24});Avoid side effects: Try to ensure that functions don't modify variables outside their scope or the objects and arrays passed to them (the function receives a reference to the same object, so the change is visible outside).
Return value conventions: Be consistent in returning values. Avoid functions that sometimes return a value and sometimes don't.
Error handling: Always consider potential errors and handle them appropriately using try-catch blocks or returning status objects.
1function cloneDinosaur(dna) {
2 try {
3 if (!dna || dna.length < 100) {
4 throw new Error("Insufficient DNA for cloning");
5 }
6
7 // Cloning code...
8
9 return {
10 success: true,
11 dinosaur: { species: "Velociraptor", id: "VR-" + Math.floor(Math.random() * 1000) }
12 };
13 } catch (error) {
14 console.error(`Cloning error: ${error.message}`);
15 return {
16 success: false,
17 error: error.message
18 };
19 }
20}The Future of JavaScript - TC39 and Language Development Proposals
Just as dinosaur DNA constantly evolved to adapt to a changing environment, JavaScript also undergoes a continuous process of evolution. Behind this process stands TC39 - the technical committee responsible for the development of the JavaScript language.
What is TC39?
TC39 (Technical Committee 39) is a group of experts that manages the development of the ECMAScript specification (the official name of the JavaScript standard). TC39 includes representatives from companies such as Google, Mozilla, Apple, Microsoft, as well as other organizations and independent experts.
Just as the scientific council of Jurassic Park decides which dinosaur species will be bred and how they will be managed, TC39 decides which new features will be added to JavaScript and in what form.
The Proposal Process - Stages 0-4
Every new feature in JavaScript goes through stages 0, 1, 2, 2.7, 3 and 4, from idea to implementation:
Stage 0 - Strawman
The earliest stage - it's like the first sketch of a new dinosaur species on paper. Anyone can submit an idea. There are no formal requirements; it's simply a place for sharing ideas.
Stage 1 - Proposal
The committee has decided that the idea is worth considering. It's like the phase when Jurassic Park scientists decided it was worth seriously considering cloning a specific species. At this stage:
- The problem that the proposal aims to solve is identified
- A general solution is described
- Potential challenges are identified
Stage 2 - Draft
The proposal now has a preliminary technical specification. It's like a detailed genetic plan and breeding procedures for a new dinosaur. At this stage:
- The syntax is largely shaped
- Semantics are formally described
- The feature is expected to be eventually included in the language
Stage 2.7 - Approved specification (since 2024)
The committee has approved the specification, and conformance tests (test262) are being written. Browsers start implementing the feature once the tests exist.
Stage 3 - Candidate
The specification is complete and awaiting implementation feedback. It's like the first cloning attempts - we have a complete plan, now we test it in practice. At this stage:
- Browsers and environments begin implementing the feature
- Feedback from developers is collected
- Only minor corrections are made
Stage 4 - Finished
The proposal is ready to be included in the official ECMAScript specification! It's like the moment when a new dinosaur successfully hatches and is ready for presentation in the park. At this stage:
- At least two independent implementations exist
- Tests are written and accepted
- The feature will be included in the next version of ECMAScript
Interesting Proposals at Various Stages
Let's look at a few fascinating proposals that could change the way we write JavaScript code:
Pipeline Operator (|>) - Stage 2
The pipeline operator allows chaining operations in a more readable way, similar to water transport channels in Jurassic Park:
1// Without pipeline operator
2const result = Math.round(Math.max(5, 10, 15) * 2);
3
4// With pipeline operator (% is the result of the previous step)
5const result = Math.max(5, 10, 15)
6 |> % * 2
7 |> Math.round(%);
8
9// Example with park security system
10const securityStatus = fetchSensorData()
11 |> filterActiveSensors(%)
12 |> analyzeThreatLevel(%)
13 |> generateSecurityReport(%);Records & Tuples - withdrawn proposal
Records & Tuples, immutable data structures compared by value, reached Stage 2, but in 2025 the committee withdrew the proposal. It is a good example that not every proposal makes it into the language.
Pattern Matching - Stage 1
A powerful pattern matching mechanism that makes conditional code more readable. It's like a dinosaur classification system - we can precisely match actions to different types:
1// Instead of many if/else or switch statements
2const handleDinosaur = (dino) => {
3 match (dino) {
4 when ({ species: "Tyrannosaurus Rex", health: health }) if (health < 50) -> {
5 return "Call the vet for the T-Rex!";
6 }
7 when ({ diet: "carnivore", escaped: true }) -> {
8 return "ALARM! Predator has escaped!";
9 }
10 when ({ species: "Velociraptor" }) -> {
11 return "Check enclosure security";
12 }
13 when ({ health: h }) if (h > 90) -> {
14 return "Dinosaur in excellent condition";
15 }
16 default -> {
17 return "Standard monitoring procedure";
18 }
19 }
20};Decorators - Stage 3
Decorators allow modifying classes and their members in a declarative way. It's like the tag and chip system for dinosaurs - we add extra functionality without modifying the basic structure:
1// Decorator for logging method calls
2function log(method, context) {
3 return function (...args) {
4 console.log(`Calling ${context.name} with arguments: ${JSON.stringify(args)}`);
5 const result = method.apply(this, args);
6 console.log(`Result: ${result}`);
7 return result;
8 };
9}
10
11class DinosaurMonitor {
12 @log
13 checkHealth(dinosaurId) {
14 // Health checking
15 return "healthy";
16 }
17
18 @log
19 feedDinosaur(dinosaurId, foodAmount) {
20 // Feeding the dinosaur
21 return "fed";
22 }
23}
24
25// Every method call will be automatically logged!
26const monitor = new DinosaurMonitor();
27monitor.checkHealth("TREX-001");
28// Console: Calling checkHealth with arguments: ["TREX-001"]
29// Console: Result: healthyHow to Follow Language Development?
If you want to stay up to date with JavaScript's evolution, similar to how Jurassic Park scientists monitor the evolution of their dinosaurs, you can:
TC39 GitHub Repository: https://github.com/tc39/proposals
- Complete list of all proposals with their current statuses
- Discussions and technical documentation
TC39 Meeting Notes: https://github.com/tc39/notes
- Notes from committee meetings
- Insight into the decision-making process
Can I Use: https://caniuse.com
- Checking browser support for new features
- Planning when to safely use new functionality
Babel: https://babeljs.io
- Ability to experiment with new features right now
- Transpiling modern code to versions supported by older browsers
TC39 Website: https://tc39.es
- Official committee website
- Process documentation and rules
Why Follow TC39 Proposals?
- Future-proofing - knowing upcoming features allows planning application architecture with the future in mind
- Influence on the language - the community can submit feedback and influence the shape of new features
- Competitive advantage - knowledge of the latest language capabilities makes you a more valuable developer
- Better code quality - new features often offer cleaner and safer ways to solve problems
Just as Jurassic Park constantly evolves, adding new species and improving security systems, JavaScript also continuously develops. Understanding the TC39 process and following new proposals is like having a genetic map of the language's future - it allows us to prepare for what's coming and shape that future through active community participation.
Summary
Functions in JavaScript, much like specialized teams in Jurassic Park, allow you to:
- Organize code - grouping related logic in one place
- Reuse - defining logic once and using it multiple times
- Abstraction - hiding implementation details behind a simple interface
- Modularity - building complex systems from simpler, independent components
Key concepts about functions:
- Different ways to define them: declarations, expressions, arrow functions
- Parameters and arguments, including default and rest parameters
- Returning values
- Variable scope
- Higher-order functions
- Recursion
- Closures
We also learned about the TC39 mechanism and the JavaScript development process - from Stage 0 proposals to finished implementations at Stage 4. Understanding this process allows us to stay current with the language's evolution and prepare for the future of JavaScript programming.
In the next lesson, you will combine everything you have learned in the final project.
Code for this lesson: index.js
1// Functions in JavaScript
2// Different ways of defining and using functions
3
4// === Function declaration ===
5console.log("=== Function declaration ===");
6
7function checkHealth(name, health) {
8 if (health > 80) {
9 return name + " - EXCELLENT";
10 } else if (health > 50) {
11 return name + " - GOOD";
12 } else {
13 return name + " - NEEDS CARE";
14 }
15}
16
17console.log(checkHealth("T-Rex", 95));
18console.log(checkHealth("Raptor", 72));
19console.log(checkHealth("Brachio", 45));
20
21// === Default parameters ===
22console.log("\n=== Default parameters ===");
23
24function feedDinosaur(name, amount = 50) {
25 console.log(name + " fed: " + amount + " kg");
26}
27
28feedDinosaur("T-Rex", 200);
29feedDinosaur("Compy"); // will use default value 50
30
31// === Arrow functions ===
32console.log("\n=== Arrow functions ===");
33
34const calcAge = (discoveryYear) => 2024 - discoveryYear;
35
36console.log("T-Rex discovered in 1905, years of research:", calcAge(1905));
37console.log("Triceratops discovered in 1889, years of research:", calcAge(1889));
38
39// Arrow with multiple lines
40const dinoProfile = (name, weight, diet) => {
41 const threat = diet === "carnivore" ? "HIGH" : "LOW";
42 return name + " (" + weight + "kg) - Threat: " + threat;
43};
44
45console.log(dinoProfile("T-Rex", 7000, "carnivore"));
46console.log(dinoProfile("Brachio", 80000, "herbivore"));
47
48// === Functions as arguments (callback) ===
49console.log("\n=== Callback ===");
50
51const dinosaurs = ["T-Rex", "Velociraptor", "Triceratops"];
52
53dinosaurs.forEach(function(dino, index) {
54 console.log((index + 1) + ". " + dino);
55});
56
57// With an arrow function
58const weights = [7000, 15, 8000, 80000];
59const large = weights.filter(w => w > 5000);
60console.log("\nLarge dinosaurs (>5000kg):", large);
61
62// === Return ===
63console.log("\n=== Function with return ===");
64
65function findLargest(array) {
66 let max = array[0];
67 for (const value of array) {
68 if (value > max) {
69 max = value;
70 }
71 }
72 return max;
73}
74
75console.log("Heaviest:", findLargest(weights), "kg");
76
77// Your task:
78// 1. Create a function that calculates the average of an array
79// 2. Use an arrow function to filter data
80// 3. Write a function with a default parameter
81Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. What is a default parameter in a function?
2. What does a modern JavaScript engine (e.g. V8) do with a piece of code that runs very often ("hot" code)?
3. What will the expression 0 === false return in JavaScript?
4. Which web application layer is responsible for communication with the server?
5. What is the FIRST step in the JavaScript debugging process?
6. What scope do variables declared with let and const have?
Hands-on tasks in the game
- Code editor
Write a function calculateFoodPortion(diet, weightKg) that returns the daily food portion in kg: 5% of the weight for the 'carnivore' diet, 3% for 'herbivore' and 4% for 'omnivore'. Call it for a T-Rex ('carnivore', 8000) and display the result in the console.
- Horizontal ordering
Arrange the function call elements with arguments:
- Vertical ordering
Arrange the stages of defining and calling functions in JavaScript:
- Click in order
Arrange the function declaration elements in the correct order:
- Code editor
Write a function calculateFossilAge(currentYear, fossilYear) that returns the fossil's age in millions of years: (currentYear - fossilYear) / 1000000. Write years BC as negative numbers. Call it for a T-Rex (2024, -68000000) and display the result in the console.
- Click in order
Arrange the arrow function elements in the correct order:
- Code editor
You have enclosure data: const voltage = 8500 and const fenceHealth = 40. Create a variable isSafe that is true when voltage > 5000 and at the same time fenceHealth > 50 (use &&), and a variable needsAttention that is true when fenceHealth < 50 or voltage === 0 (use ||). Display both in the console.