Appearance
Course Title: "JavaScript: Functions"
Course Outline:
- Introduction to Functions
- What is a Function?
- Importance of Functions in JavaScript
- Anatomy of a Function Declaration
- Function Types
- Function Declarations
- Function Expressions
- Arrow Functions
- Immediately Invoked Function Expressions (IIFE)
- Function Parameters and Arguments
- Defining Parameters
- Passing Arguments
- Default Parameters
- Rest Parameters
- Return Values
- The return Statement
- Returning Values from Functions
- Undefined vs. Null
- Scope and Hoisting
- Function Scope
- Block Scope
- Variable Hoisting
- Higher-Order Functions
- What are Higher-Order Functions?
- Function as First-Class Citizens
- Using Functions as Arguments
- Returning Functions
- Closures
- Understanding Closures
- Creating and Using Closures
- Practical Use Cases for Closures
- Callback Functions
- What is a Callback Function?
- Synchronous vs. Asynchronous Callbacks
- Examples of Callback Functions
- Promises and Async/Await
- Introduction to Promises
- Using Promises in Functions
- The Async/Await Syntax
- Error Handling in Functions
- Try-Catch Blocks
- Throwing Errors
- Custom Error Handling
- Function Best Practices
- Naming Conventions
- Keeping Functions Small and Focused
- Documentation and Comments
Introduction:
JavaScript functions are essential building blocks in the language, allowing developers to define reusable pieces of code that can process inputs, perform operations, and return outputs. Functions help structure programs, making them more modular, easier to maintain, and scalable.
This course will explore the various aspects of functions in JavaScript, including their types, parameters, return values, scope, higher-order functions, and best practices. By the end of this course, students will understand how to effectively utilize functions in their JavaScript programs, enhancing their coding skills and improving their ability to tackle complex problems.
Main Content:
Introduction to Functions
What is a Function?
A function in JavaScript is a block of code designed to perform a specific task. It is defined once and can be called multiple times throughout a program. Functions are fundamental to programming as they enable code reuse and better organization.
Example:
javascript
function greet(name) {
return `Hello, ${name}!`;
}
console.log(greet("Alice")); // Output: Hello, Alice!
1
2
3
4
5
2
3
4
5
Explanation: In this example, the function greet
takes a parameter name
and returns a greeting message. When we call greet("Alice")
, it outputs "Hello, Alice!". This demonstrates how functions can encapsulate behavior that can be executed with different inputs, showcasing the power of reusability in programming.
Importance of Functions in JavaScript
Functions are vital for code organization, reusability, and abstraction. They allow developers to break down complex problems into smaller, manageable parts. By using functions, programmers can define clear interfaces and hide implementation details, thus making the code cleaner and easier to understand.
Example:
javascript
function calculateArea(radius) {
return Math.PI * radius * radius;
}
console.log(calculateArea(5)); // Output: 78.53981633974483
1
2
3
4
5
2
3
4
5
Explanation: The calculateArea
function encapsulates the logic for calculating the area of a circle, making it reusable whenever this calculation is needed. This not only enhances code readability but also reduces redundancy, as the same function can be employed in various parts of the codebase whenever the area needs to be computed.
Anatomy of a Function Declaration
A function declaration consists of the function
keyword, followed by a name, parentheses (which may include parameters), and a block of code enclosed in curly braces. Understanding the structure of function declarations is crucial for writing effective JavaScript code.
Example:
javascript
function multiply(a, b) {
return a * b;
}
1
2
3
2
3
Explanation: The function multiply
takes two parameters, a
and b
, and returns their product. The function's name signifies its purpose, which is to multiply two numbers. By following this structure, developers can create functions that are intuitive and easy to use.
Key Takeaways:
- Functions are reusable blocks of code.
- They help in organizing and structuring code.
- Understanding function declarations is fundamental for effective JavaScript programming.
Function Types
Function Declarations
A function declaration is a way to define a function using the function
keyword. It is hoisted, meaning it can be called before its declaration in the code. This feature allows for flexibility in how functions are structured within a program.
Example:
javascript
console.log(add(3, 4)); // Output: 7
function add(x, y) {
return x + y;
}
1
2
3
4
5
2
3
4
5
Explanation: The add
function can be called before its declaration, demonstrating hoisting. This is particularly useful in larger codebases where the order of function definitions may vary, allowing for more freedom in coding style.
Function Expressions
A function expression defines a function as part of an expression. Unlike function declarations, function expressions are not hoisted, meaning they cannot be called before they are defined in the code.
Example:
javascript
const subtract = function(x, y) {
return x - y;
};
console.log(subtract(10, 5)); // Output: 5
1
2
3
4
5
2
3
4
5
Explanation: Here, subtract
is defined as a function expression. It can only be called after its definition, which emphasizes the importance of understanding the scope of function expressions in JavaScript.
Arrow Functions
Arrow functions provide a more concise syntax for writing functions in JavaScript. They are anonymous and do not have their own this
context, which can simplify certain scenarios, especially in callback functions.
Example:
javascript
const divide = (a, b) => a / b;
console.log(divide(10, 2)); // Output: 5
1
2
3
2
3
Explanation: The divide
function uses arrow function syntax, making it shorter and cleaner. This syntax not only reduces boilerplate code but also helps in maintaining the this
context from the enclosing lexical scope, which is particularly beneficial in certain programming patterns.
Immediately Invoked Function Expressions (IIFE)
IIFEs are functions that are executed immediately after they are defined. They help create a new scope, which is useful for avoiding polluting the global namespace.
Example:
javascript
(function() {
console.log("This is an IIFE");
})();
1
2
3
2
3
Explanation: The above code defines and immediately invokes a function, outputting "This is an IIFE". This pattern is often used in JavaScript to encapsulate logic and variables, preventing them from being accessed globally.
Key Takeaways:
- Function declarations are hoisted, while function expressions are not.
- Arrow functions provide a concise syntax and have lexical scoping for
this
. - IIFEs help create a new scope to avoid global namespace pollution.
Function Parameters and Arguments
Defining Parameters
Parameters are variables listed as part of a function's definition. They act as placeholders for the values (arguments) that will be passed to the function when it is called. This allows functions to operate on different inputs dynamically.
Example:
javascript
function power(base, exponent) {
return base ** exponent;
}
1
2
3
2
3
Explanation: In the power
function, base
and exponent
are parameters used to compute the power of a number. This allows the function to be reused with different values for base
and exponent
, promoting flexibility in calculations.
Passing Arguments
Arguments are the actual values passed to the function when it is invoked. Understanding the difference between parameters and arguments is crucial for effective function usage.
Example:
javascript
console.log(power(2, 3)); // Output: 8
1
Explanation: Here, 2
and 3
are the arguments passed to the power
function. The ability to pass different arguments enables functions to handle a variety of cases with minimal changes to the code.
Default Parameters
Default parameters allow you to initialize named parameters with default values if no value or undefined
is passed during function invocation. This feature enhances the robustness of functions by providing fallbacks.
Example:
javascript
function greet(name = "Guest") {
return `Hello, ${name}!`;
}
console.log(greet()); // Output: Hello, Guest!
1
2
3
4
5
2
3
4
5
Explanation: The greet
function uses a default parameter. If no argument is provided, it defaults to "Guest". This is particularly useful for creating user-friendly functions that can operate without requiring every piece of data.
Rest Parameters
Rest parameters allow a function to accept an indefinite number of arguments as an array, which is useful for functions that need to handle various inputs dynamically.
Example:
javascript
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4)); // Output: 10
1
2
3
4
5
2
3
4
5
Explanation: The sum
function uses the rest parameter ...numbers
, allowing it to accept any number of arguments and calculate their sum. This capability is valuable for functions that need to be flexible in terms of input size.
Key Takeaways:
- Parameters act as placeholders in function definitions.
- Arguments are the actual values passed to functions.
- Default parameters provide fallback values, while rest parameters allow for variable input lengths.
Return Values
The return Statement
The return
statement ends function execution and specifies a value to be returned to the function caller. This is a fundamental concept in programming, as it allows functions to produce results that can be used elsewhere in the code.
Example:
javascript
function square(number) {
return number * number;
}
1
2
3
2
3
Explanation: The square
function uses the return
statement to send back the squared value of the input. The ability to return values is what enables functions to be powerful tools in building complex logic.
Returning Values from Functions
When a function is called, it can return data that can be used in the calling code. This interaction between functions and the calling environment is essential for building modular applications.
Example:
javascript
let result = square(4);
console.log(result); // Output: 16
1
2
2
Explanation: The returned value from square(4)
is stored in result
and then logged. This demonstrates how functions can encapsulate logic and return results that can be manipulated or displayed.
Undefined vs. Null
In JavaScript, undefined
indicates a variable that has been declared but not yet assigned a value, while null
is an assignment value that represents "no value". Understanding this distinction is crucial for effective error handling and data validation.
Example:
javascript
function noReturn() {}
console.log(noReturn()); // Output: undefined
1
2
3
2
3
Explanation: The noReturn
function does not explicitly return a value, resulting in undefined
when logged. Recognizing the difference between undefined
and null
can help developers avoid common pitfalls in their code.
Key Takeaways:
- The
return
statement is essential for producing output from functions. - Functions can interact with their calling environment through return values.
- Understanding the difference between
undefined
andnull
is important for data handling.
Scope and Hoisting
Function Scope
Variables defined within a function are local to that function and cannot be accessed outside of it. This concept of scope is fundamental in managing variable visibility and lifecycle in JavaScript.
Example:
javascript
function myFunction() {
let localVar = "I'm local!";
console.log(localVar);
}
myFunction(); // Output: I'm local!
// console.log(localVar); // Uncaught ReferenceError: localVar is not defined
1
2
3
4
5
6
7
2
3
4
5
6
7
Explanation: The variable localVar
is defined within myFunction
and cannot be accessed outside it. This encapsulation of variables helps prevent conflicts and unintended interactions in larger codebases.
Block Scope
With ES6, variables defined with let
and const
are block-scoped, meaning they are only accessible within the block they are defined in. This is an important feature for controlling variable visibility and improving code structure.
Example:
javascript
{
let blockScoped = "I'm block scoped!";
console.log(blockScoped); // Output: I'm block scoped!
}
// console.log(blockScoped); // Uncaught ReferenceError: blockScoped is not defined
1
2
3
4
5
2
3
4
5
Explanation: The variable blockScoped
is only accessible within the block, ensuring that it does not interfere with variables in other scopes. This encourages better coding practices by limiting variable lifetimes.
Variable Hoisting
In JavaScript, variable and function declarations are hoisted to the top of their containing scope, meaning they can be referenced before they are declared. This behavior can sometimes lead to confusion for developers.
Example:
javascript
console.log(hoistedVar); // Output: undefined
var hoistedVar = "I am hoisted!";
1
2
2
Explanation: The declaration of hoistedVar
is hoisted, but its assignment happens at runtime, resulting in undefined
when logged before the assignment. Understanding hoisting is critical for predicting how code will execute.
Key Takeaways:
- Function scope ensures variables are local to their functions.
- Block scope allows for better control over variable visibility.
- Hoisting can lead to unexpected behavior if not understood properly.
Higher-Order Functions
What are Higher-Order Functions?
A higher-order function is a function that can take other functions as arguments or return a function as its result. This concept is central to functional programming and enables powerful abstractions.
Example:
javascript
function higherOrderFunction(fn) {
return function(x) {
return fn(x) + 1;
};
}
const addOne = higherOrderFunction(x => x);
console.log(addOne(5)); // Output: 6
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Explanation: The higherOrderFunction
takes a function fn
and returns a new function that adds 1 to the output of fn
. This allows for creating versatile functions that can modify their behavior based on the passed function.
Function as First-Class Citizens
In JavaScript, functions are first-class citizens, meaning they can be treated like any other variable (assigned to variables, passed as arguments, returned from other functions). This characteristic is what facilitates the creation of higher-order functions.
Example:
javascript
function executeFunction(fn) {
return fn();
}
console.log(executeFunction(() => "Executed Function")); // Output: Executed Function
1
2
3
4
5
2
3
4
5
Explanation: The executeFunction
takes a function fn
as an argument and executes it. This flexibility allows for dynamic behavior in code, making JavaScript a powerful language for functional programming.
Using Functions as Arguments
You can pass functions as arguments to other functions, enabling powerful functional programming patterns. This capability allows for a more declarative coding style.
Example:
javascript
function processArray(arr, fn) {
return arr.map(fn);
}
const doubled = processArray([1, 2, 3], x => x * 2);
console.log(doubled); // Output: [2, 4, 6]
1
2
3
4
5
6
2
3
4
5
6
Explanation: The processArray
function accepts an array and a function, applying the function to each element in the array. This showcases how functions can be modular and reusable across different contexts.
Returning Functions
Functions can return other functions, allowing for dynamic behavior and the creation of function factories.
Example:
javascript
function multiplier(factor) {
return function(x) {
return x * factor;
};
}
const double = multiplier(2);
console.log(double(5)); // Output: 10
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Explanation: The multiplier
function returns a new function that multiplies its input by factor
. This pattern is useful for creating specialized functions based on a common behavior.
Key Takeaways:
- Higher-order functions can take or return other functions.
- Functions in JavaScript are first-class citizens, allowing for dynamic programming patterns.
- Using functions as arguments promotes modularity and reusability.
Closures
Understanding Closures
A closure is a function that retains access to its lexical scope, even when the function is executed outside that scope. Closures are a powerful feature in JavaScript that enable data encapsulation and private variables.
Example:
javascript
function makeCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // Output: 1
console.log(counter()); // Output: 2
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Explanation: The inner function retains access to the count
variable from its outer function, allowing it to increment and maintain its state. This encapsulation is useful for creating private data that cannot be accessed directly from outside the closure.
Creating and Using Closures
Closures are commonly used for data encapsulation and creating private variables. This helps to protect the internal state of an object or function from external interference.
Example:
javascript
function createSecret() {
let secret = "I am secret!";
return function() {
return secret;
};
}
const revealSecret = createSecret();
console.log(revealSecret()); // Output: I am secret!
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Explanation: The createSecret
function creates a closure that retains access to the secret
variable. This pattern allows functions to maintain state and encapsulate data effectively.
Practical Use Cases for Closures
Closures are useful for creating functions with private data and event handlers that need to access surrounding scope. They enable powerful programming patterns that improve modularity and separation of concerns.
Example:
javascript
function buttonHandler() {
let clicks = 0;
return function() {
clicks++;
console.log(`Button clicked ${clicks} times`);
};
}
const handleClick = buttonHandler();
handleClick(); // Output: Button clicked 1 times
handleClick(); // Output: Button clicked 2 times
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Explanation: The button handler closure keeps track of how many times the button has been clicked. This pattern is helpful in scenarios where you need to maintain state without exposing it globally.
Key Takeaways:
- Closures retain access to their lexical scope.
- They enable data encapsulation and private variables.
- Closures are useful for creating functions that manage state effectively.
Callback Functions
What is a Callback Function?
A callback function is a function passed into another function as an argument, which is then invoked inside that function. Callbacks are fundamental for handling asynchronous operations in JavaScript.
Example:
javascript
function fetchData(callback) {
setTimeout(() => {
const data = { id: 1, name: "John" };
callback(data);
}, 1000);
}
fetchData(data => console.log(data)); // After 1 second: { id: 1, name: 'John' }
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Explanation: The fetchData
function simulates an asynchronous operation and invokes the callback
with the fetched data after a delay. This pattern is essential for managing asynchronous behavior in JavaScript.
Synchronous vs. Asynchronous Callbacks
Synchronous callbacks are executed immediately, while asynchronous callbacks are executed after a certain event or delay. Understanding the difference between these types of callbacks is critical for effective asynchronous programming.
Example of Synchronous Callback:
javascript
function greet(name, callback) {
console.log(`Hello, ${name}!`);
callback();
}
greet("Alice", () => console.log("Nice to meet you!"));
// Output: Hello, Alice!
// Nice to meet you!
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Explanation: The callback is executed immediately after greeting, demonstrating synchronous behavior.
Example of Asynchronous Callback:
javascript
setTimeout(() => {
console.log("This runs after 2 seconds");
}, 2000);
1
2
3
2
3
Explanation: The callback in setTimeout
runs after a 2-second delay, illustrating asynchronous behavior.
Examples of Callback Functions
Callbacks are widely used in JavaScript, especially in handling events and asynchronous operations. They provide a way to define actions that should occur in response to specific events.
Example:
javascript
document.getElementById("myButton").addEventListener("click", () => {
console.log("Button clicked!");
});
1
2
3
2
3
Explanation: The anonymous function is a callback that executes when the button is clicked, showcasing how event-driven programming works in JavaScript.
Key Takeaways:
- Callback functions are essential for handling asynchronous operations.
- Synchronous and asynchronous callbacks serve different purposes.
- Callbacks enhance interactivity and responsiveness in applications.
Promises and Async/Await
Introduction to Promises
A Promise is an object that represents the eventual completion or failure of an asynchronous operation and its resulting value. Promises provide a cleaner alternative to traditional callback-based approaches for handling asynchronous code.
Example:
javascript
let myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data received!");
}, 1000);
});
myPromise.then(data => console.log(data)); // Output: Data received! after 1 second
1
2
3
4
5
6
7
2
3
4
5
6
7
Explanation: The promise resolves after 1 second, invoking the then
method with the result. This pattern improves readability and maintains a clearer flow of asynchronous operations.
Using Promises in Functions
Functions can return promises, allowing for better handling of asynchronous operations and chaining of actions.
Example:
javascript
function fetchUser() {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ id: 1, name: "Alice" });
}, 1000);
});
}
fetchUser().then(user => console.log(user)); // Output: { id: 1, name: 'Alice' } after 1 second
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Explanation: The fetchUser
function returns a promise that resolves with user data, demonstrating how promises can be integrated into function workflows.
The Async/Await Syntax
Async functions provide a way to work with promises in a more readable manner. The await
keyword can be used to pause execution until the promise is resolved, making asynchronous code look more like synchronous code.
Example:
javascript
async function getUser() {
const user = await fetchUser();
console.log(user);
}
getUser(); // Output: { id: 1, name: 'Alice' } after 1 second
1
2
3
4
5
6
2
3
4
5
6
Explanation: The getUser
function waits for fetchUser
to resolve before logging the user data, making the asynchronous flow easier to read and understand.
Key Takeaways:
- Promises provide a cleaner way to handle asynchronous operations.
- Functions can return promises for improved chaining and error handling.
- Async/await syntax simplifies asynchronous code and enhances readability.
Error Handling in Functions
Try-Catch Blocks
The try-catch
statement allows you to handle exceptions gracefully in JavaScript. This mechanism prevents the program from crashing and provides a way to respond to errors in a controlled manner.
Example:
javascript
function riskyFunction() {
throw new Error("Something went wrong!");
}
try {
riskyFunction();
} catch (error) {
console.log(error.message); // Output: Something went wrong!
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Explanation: The riskyFunction
throws an error, which is caught by the catch
block. This demonstrates how to manage errors and respond appropriately without halting the execution of the program.
Throwing Errors
You can manually throw errors using the throw
statement, which enables you to create custom error handling logic based on specific conditions.
Example:
javascript
function validateAge(age) {
if (age < 18) {
throw new Error("You must be at least 18 years old.");
}
return "Access granted.";
}
try {
console.log(validateAge(16));
} catch (error) {
console.log(error.message); // Output: You must be at least 18 years old.
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Explanation: The validateAge
function throws an error if the age is below 18, showcasing how to enforce business rules and handle invalid input.
Custom Error Handling
You can create custom error classes to handle specific types of errors in a more structured way. This approach allows for clearer error identification and responses.
Example:
javascript
class CustomError extends Error {
constructor(message) {
super(message);
this.name = "CustomError";
}
}
function test() {
throw new CustomError("This is a custom error!");
}
try {
test();
} catch (error) {
console.log(error.name + ": " + error.message); // Output: CustomError: This is a custom error!
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Explanation: The CustomError
class provides a specific error type that can be caught and handled, enhancing the maintainability and clarity of error handling in your code.
Key Takeaways:
- Try-catch blocks enable graceful error handling.
- Manual error throwing allows for custom error management.
- Custom error classes enhance clarity and organization in error handling.
Function Best Practices
Naming Conventions
Use descriptive names for functions that clearly indicate their purpose. Functions should be named using camelCase to ensure consistency and readability.
Example:
javascript
function calculateTotalPrice(price, quantity) {
return price * quantity;
}
1
2
3
2
3
Explanation: The name calculateTotalPrice
clearly describes what the function does, making it easier for other developers to understand its purpose at a glance.
Keeping Functions Small and Focused
Aim to write small, single-purpose functions. Each function should do one thing well, promoting better readability and easier testing.
Example:
javascript
function isEven(num) {
return num % 2 === 0;
}
function filterEvens(arr) {
return arr.filter(isEven);
}
1
2
3
4
5
6
7
2
3
4
5
6
7
Explanation: The isEven
function checks if a number is even, while filterEvens
uses it to filter an array. This separation of concerns allows for better maintenance and testing of individual functionalities.
Documentation and Comments
Document your functions with comments to describe their parameters, return values, and behavior. This practice improves code maintainability and helps other developers understand your code.
Example:
javascript
/**
* Calculates the factorial of a number.
* @param {number} n - The number to calculate the factorial for.
* @returns {number} - The factorial of the number.
*/
function factorial(n) {
if (n === 0) return 1;
return n * factorial(n - 1);
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Explanation: The documentation comments help other developers understand how to use the factorial
function, providing essential context and usage guidelines.
Key Takeaways:
- Descriptive naming improves readability and understanding.
- Small, focused functions enhance maintainability.
- Proper documentation is crucial for collaborative coding and future reference.
JavaScript Functions Examples
1. Basic Greeting Function ★☆☆
javascript
function greet() {
return "Hello, World!";
}
console.log(greet()); // Output: Hello, World!
1
2
3
4
5
2
3
4
5
Explanation: This basic function greet
returns a simple greeting message. It demonstrates the fundamental structure of a function in JavaScript.
2. Simple Addition Function ★☆☆
javascript
function add(a, b) {
return a + b;
}
console.log(add(5, 3)); // Output: 8
1
2
3
4
5
2
3
4
5
Explanation: The add
function takes two parameters and returns their sum. This example illustrates how functions can take inputs and provide outputs.
3. Function with Default Parameters ★☆☆
javascript
function multiply(a, b = 1) {
return a * b;
}
console.log(multiply(5)); // Output: 5
1
2
3
4
5
2
3
4
5
Explanation: The multiply
function has a default parameter for b
. If no argument is provided, it defaults to 1
, demonstrating how default parameters work.
4. Using Rest Parameters ★☆☆
javascript
function concatenate(...strings) {
return strings.join(" ");
}
console.log(concatenate("Hello", "world!", "How", "are", "you?")); // Output: Hello world! How are you?
1
2
3
4
5
2
3
4
5
Explanation: The concatenate
function uses rest parameters to accept any number of string arguments and joins them into a single string.
5. Anonymous Function Expression ★★☆
javascript
const square = function(x) {
return x * x;
};
console.log(square(4)); // Output: 16
1
2
3
4
5
2
3
4
5
Explanation: Here, square
is defined as an anonymous function expression. This shows how functions can be assigned to variables.
6. Arrow Function Syntax ★★☆
javascript
const subtract = (a, b) => a - b;
console.log(subtract(10, 5)); // Output: 5
1
2
3
2
3
Explanation: The subtract
function is defined using the arrow function syntax, which is more concise and maintains the this
context.
7. Immediately Invoked Function Expression (IIFE) ★★☆
javascript
(function() {
console.log("IIFE executed!");
})();
1
2
3
2
3
Explanation: This IIFE runs immediately after it is defined, demonstrating how to execute a function without calling it explicitly.
8. Function Returning Another Function ★★☆
javascript
function makeMultiplier(multiplier) {
return function(x) {
return x * multiplier;
};
}
const double = makeMultiplier(2);
console.log(double(5)); // Output: 10
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Explanation: The makeMultiplier
function returns a new function that can multiply its input by the given multiplier, showcasing closures.
9. Callback Function Example ★★☆
javascript
function fetchData(callback) {
setTimeout(() => {
const data = { id: 1, name: "Alice" };
callback(data);
}, 1000);
}
fetchData(data => console.log(data)); // After 1 second: { id: 1, name: 'Alice' }
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Explanation: This example demonstrates a function that takes a callback and invokes it after simulating an asynchronous operation using setTimeout
.
10. Higher-Order Function ★★☆
javascript
function applyOperation(arr, operation) {
return arr.map(operation);
}
const results = applyOperation([1, 2, 3], x => x * 2);
console.log(results); // Output: [2, 4, 6]
1
2
3
4
5
6
2
3
4
5
6
Explanation: The applyOperation
function takes an array and a function as arguments, applying the operation to each element in the array.
11. Error Handling with Try-Catch ★★☆
javascript
function riskyFunction() {
throw new Error("Risky operation failed!");
}
try {
riskyFunction();
} catch (error) {
console.log(error.message); // Output: Risky operation failed!
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Explanation: This example shows how to handle errors using try-catch
, allowing graceful recovery from exceptions.
12. Promise Example ★★☆
javascript
function fetchUser() {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ id: 1, name: "Bob" });
}, 1000);
});
}
fetchUser().then(user => console.log(user)); // Output: { id: 1, name: 'Bob' } after 1 second
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Explanation: The fetchUser
function returns a promise that resolves with user data after a delay, illustrating how to work with asynchronous operations.
13. Async/Await Example ★★☆
javascript
async function getUser() {
const user = await fetchUser();
console.log(user);
}
getUser(); // Output: { id: 1, name: 'Bob' } after 1 second
1
2
3
4
5
6
2
3
4
5
6
Explanation: The getUser
function uses async/await syntax to handle the promise returned by fetchUser
, making the code easier to read.
14. Closure Example ★★★
javascript
function counter() {
let count = 0;
return function() {
count++;
return count;
};
}
const increment = counter();
console.log(increment()); // Output: 1
console.log(increment()); // Output: 2
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Explanation: The counter
function returns a closure that maintains access to the count
variable, allowing it to keep track of how many times it has been called.
15. Custom Error Class ★★★
javascript
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
function validate(value) {
if (value < 0) {
throw new ValidationError("Negative values are not allowed.");
}
}
try {
validate(-1);
} catch (error) {
console.log(error.name + ": " + error.message); // Output: ValidationError: Negative values are not allowed.
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Explanation: This example defines a custom error class ValidationError
, demonstrating how to create specific error types for better error handling.
16. Function Composition ★★★
javascript
function compose(f, g) {
return function(x) {
return f(g(x));
};
}
const addOne = x => x + 1;
const square = x => x * x;
const addOneThenSquare = compose(square, addOne);
console.log(addOneThenSquare(2)); // Output: 9
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Explanation: The compose
function takes two functions and returns a new function that applies them in sequence, demonstrating function composition.
17. Memoization Example ★★★
javascript
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
}
const result = fn(...args);
cache[key] = result;
return result;
};
}
const factorial = memoize(function(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
});
console.log(factorial(5)); // Output: 120
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Explanation: The memoize
function caches the results of a function to optimize performance, especially for expensive calculations like factorial.
18. Function Chaining ★★★
javascript
class Calculator {
constructor(value = 0) {
this.value = value;
}
add(num) {
this.value += num;
return this;
}
multiply(num) {
this.value *= num;
return this;
}
getResult() {
return this.value;
}
}
const result = new Calculator()
.add(2)
.multiply(3)
.add(5)
.getResult();
console.log(result); // Output: 11
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Explanation: The Calculator
class allows for method chaining by returning this
, enabling a fluent interface for performing calculations.
19. Throttling Function Example ★★★
javascript
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function() {
const context = this;
const args = arguments;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(() => {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
}
const log = throttle(() => console.log("Throttled!"), 2000);
setInterval(log, 500); // Logs "Throttled!" every 2 seconds
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Explanation: The throttle
function limits the rate at which a function can be called, useful for performance optimization in scenarios like window resizing events.
20. Debouncing Function Example ★★★
javascript
function debounce(func, delay) {
let timeout;
return function() {
const context = this;
const args = arguments;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), delay);
};
}
const search = debounce(() => console.log("Searching..."), 300);
document.getElementById("searchInput").addEventListener("input", search);
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Explanation: The debounce
function ensures that a function is not called again until a certain amount of time has passed since the last call, useful for scenarios like search input fields to limit API requests.
These examples illustrate various concepts and best practices related to functions in JavaScript, ranging from basic to advanced usage, helping students understand the versatility and power of functions in the language.
JavaScript Functions Exercises
1. Basic Sum Function ★☆ύ fourth;
Create a function named sum
that takes two parameters and returns their sum.
javascript
function sum(a, b) {
return a + b;
}
// Test the function
console.log(sum(3, 4)); // Output: 7
1
2
3
4
5
6
2
3
4
5
6
Explanation: This exercise focuses on defining a basic function that accepts two numbers as parameters and returns their sum. It demonstrates fundamental function syntax and usage.
2. Greeting Function with Name Parameter ★☆☆
Develop a function called greetUser
that takes a name as an argument and returns a greeting message.
javascript
function greetUser(name) {
return `Hello, ${name}!`;
}
// Test the function
console.log(greetUser("Alice")); // Output: Hello, Alice!
1
2
3
4
5
6
2
3
4
5
6
Explanation: This function enhances understanding of parameters by requiring a user's name to personalize the greeting. It reinforces string interpolation within JavaScript functions.
3. Function with Default Parameters ★☆☆
Create a function multiply
that takes two parameters, a
and b
, where b
has a default value of 1
. Return the product.
javascript
function multiply(a, b = 1) {
return a * b;
}
// Test the function
console.log(multiply(5)); // Output: 5
console.log(multiply(5, 3)); // Output: 15
1
2
3
4
5
6
7
2
3
4
5
6
7
Explanation: This exercise illustrates how default parameters work, allowing the function to operate correctly even when the second argument is not provided.
4. Rest Parameters Function ★☆☆
Implement a function called collectArgs
that uses rest parameters to accept any number of arguments and returns their sum.
javascript
function collectArgs(...args) {
return args.reduce((total, num) => total + num, 0);
}
// Test the function
console.log(collectArgs(1, 2, 3, 4)); // Output: 10
1
2
3
4
5
6
2
3
4
5
6
Explanation: This exercise teaches how to use rest parameters to gather an indefinite number of arguments into an array, demonstrating array manipulation through the reduce
method.
5. Anonymous Function Expression ★★☆
Define a variable subtract
that holds an anonymous function for subtracting two numbers.
javascript
const subtract = function(a, b) {
return a - b;
};
// Test the function
console.log(subtract(10, 4)); // Output: 6
1
2
3
4
5
6
2
3
4
5
6
Explanation: This exercise explores function expressions, showing how to assign a function to a variable and call it later.
6. Arrow Function Implementation ★★☆
Create an arrow function named divide
that divides two numbers.
javascript
const divide = (a, b) => a / b;
// Test the function
console.log(divide(8, 2)); // Output: 4
1
2
3
4
2
3
4
Explanation: This exercise introduces arrow functions, demonstrating their concise syntax and how they can be used to define simple operations.
7. Immediately Invoked Function Expression (IIFE) ★★☆
Write an IIFE that logs "Executing IIFE!" to the console.
javascript
(function() {
console.log("Executing IIFE!");
})();
1
2
3
2
3
Explanation: This example illustrates how to define and execute a function immediately, showcasing the IIFE pattern commonly used for creating private scopes.
8. Higher-Order Function ★★☆
Create a higher-order function createMultiplier
that returns a function for multiplying by a specified factor.
javascript
function createMultiplier(factor) {
return function(x) {
return x * factor;
};
}
// Test the function
const double = createMultiplier(2);
console.log(double(5)); // Output: 10
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Explanation: This exercise demonstrates higher-order functions, which can return other functions, allowing for dynamic behavior based on the closure.
9. Callback Function Usage ★★☆
Develop a function fetchData
that simulates an asynchronous operation and accepts a callback to process the result.
javascript
function fetchData(callback) {
setTimeout(() => {
const data = { id: 1, name: "John" };
callback(data);
}, 1000);
}
// Test the function
fetchData(data => {
console.log(data); // Output: { id: 1, name: 'John' } after 1 second
});
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Explanation: This exercise illustrates the concept of callback functions, particularly in asynchronous programming, where the callback is invoked after a delay.
10. Promise-based Function ★★☆
Create a function getUser
that returns a promise resolving with user data.
javascript
function getUser() {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ id: 1, name: "Alice" });
}, 1000);
});
}
// Test the function
getUser().then(user => console.log(user)); // Output: { id: 1, name: 'Alice' } after 1 second
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Explanation: This exercise introduces promises, allowing students to understand how to handle asynchronous operations and their results in JavaScript.
11. Async/Await Function ★★☆
Write an async function fetchUser
that utilizes async/await syntax to get user data.
javascript
async function fetchUser() {
const user = await getUser();
console.log(user);
}
// Test the function
fetchUser(); // Output: { id: 1, name: 'Alice' } after 1 second
1
2
3
4
5
6
7
2
3
4
5
6
7
Explanation: This example enhances understanding of asynchronous programming using async/await, making the code easier to read and manage.
12. Closure Example ★★★
Construct a function counter
that creates a closure, returning a function to increment a counter.
javascript
function counter() {
let count = 0;
return function() {
count++;
return count;
};
}
// Test the function
const increment = counter();
console.log(increment()); // Output: 1
console.log(increment()); // Output: 2
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Explanation: This exercise demonstrates closures by creating a private state (count
) that persists between function calls.
13. Error Handling with Try-Catch ★★★
Write a function throwError
that throws an error, and implement error handling using try-catch.
javascript
function throwError() {
throw new Error("An error occurred!");
}
try {
throwError();
} catch (error) {
console.log(error.message); // Output: An error occurred!
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Explanation: This exercise teaches how to handle exceptions in JavaScript using try-catch, allowing for graceful error management.
14. Custom Error Class Implementation ★★★
Create a custom error class ValidationError
and use it in a function that validates input.
javascript
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
function validateInput(input) {
if (input < 0) {
throw new ValidationError("Input must be a non-negative number.");
}
}
// Test the function
try {
validateInput(-1);
} catch (error) {
console.log(error.message); // Output: Input must be a non-negative number.
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Explanation: This exercise shows how to create and throw a custom error, enhancing the understanding of structured error handling in JavaScript.
15. Function Composition ★★★
Implement a function compose
that takes two functions and returns a new function that applies them in sequence.
javascript
function compose(f, g) {
return function(x) {
return f(g(x));
};
}
// Test the function
const addOne = x => x + 1;
const square = x => x * x;
const addOneThenSquare = compose(square, addOne);
console.log(addOneThenSquare(2)); // Output: 9
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Explanation: This exercise teaches function composition, demonstrating how to combine functions to create new behavior.
16. Memoization Example ★★★
Write a memoize
function that caches the results of a computationally expensive function.
javascript
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
}
const result = fn(...args);
cache[key] = result;
return result;
};
}
// Test the function
const factorial = memoize(function(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
});
console.log(factorial(5)); // Output: 120
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Explanation: This exercise illustrates how to optimize functions using memoization, enhancing performance by caching results.
17. Debounce Function Example ★★★
Create a debounce
function that limits how often a function can be invoked.
javascript
function debounce(func, delay) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), delay);
};
}
// Test the function
const log = debounce(() => console.log("Debounced!"), 1000);
setInterval(log, 300); // Logs "Debounced!" every 1 second
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Explanation: This exercise teaches the concept of debouncing, useful for limiting the rate of function execution, particularly in event handling scenarios.
18. Throttle Function Example ★★★
Implement a throttle
function that restricts how often a function can be called.
javascript
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function(...args) {
const context = this;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(() => {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
}
// Test the function
const log = throttle(() => console.log("Throttled!"), 2000);
setInterval(log, 500); // Logs "Throttled!" every 2 seconds
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Explanation: This exercise demonstrates throttling, a technique that limits how often a function can execute, useful for performance-intensive operations.
19. Event Handling with Callback Functions ★★★
Create a button in HTML and write a JavaScript function to handle click events using a callback.
html
<button id="myButton">Click Me!</button>
<script>
document.getElementById("myButton").addEventListener("click", function() {
console.log("Button clicked!");
});
</script>
1
2
3
4
5
6
7
2
3
4
5
6
7
Explanation: This exercise combines HTML and JavaScript, showing how to use callback functions for event handling in a web environment.
20. Function to Convert Celsius to Fahrenheit ★★★
Develop a function celsiusToFahrenheit
that converts Celsius to Fahrenheit.
javascript
function celsiusToFahrenheit(celsius) {
return (celsius * 9/5) + 32;
}
// Test the function
console.log(celsiusToFahrenheit(0)); // Output: 32
console.log(celsiusToFahrenheit(100)); // Output: 212
1
2
3
4
5
6
7
2
3
4
5
6
7
Explanation: This exercise reinforces the concept of functions by applying a mathematical formula, allowing students to practice parameter usage and return values.
These exercises progress in complexity from basic function creation to advanced concepts like closures, error handling, and functional programming techniques. Each exercise is designed to reinforce essential concepts and encourage students to practice their JavaScript skills effectively.
Quiz about: "JavaScript: functions"
Question 1:
What is the correct way to define a function in JavaScript?
javascript
A) function myFunction() {}
B) define myFunction() {}
C) function: myFunction() {}
D) myFunction = function() {}
E) function => myFunction() {}
1
2
3
4
5
2
3
4
5
The correct answer: A
Question 2:
Which of the following is an example of an arrow function?
javascript
A) function() => { return "Hello"; }
B) const greet = (name) => "Hello, " + name;
C) const greet: function(name) { return "Hello, " + name; }
D) function greet(name) { return "Hello, " + name; }
E) const greet(name) => { return "Hello, " + name; }
1
2
3
4
5
2
3
4
5
The correct answer: B
Question 3:
What will the following code return?
javascript
function add(a, b = 5) {
return a + b;
}
console.log(add(2));
1
2
3
4
2
3
4
javascript
A) 2
B) 5
C) 7
D) undefined
E) NaN
1
2
3
4
5
2
3
4
5
The correct answer: C
Question 4:
What is the purpose of the return
statement in a function?
javascript
A) To end the function execution and output a value
B) To declare a new variable
C) To define a new function
D) To create a loop
E) To throw an error
1
2
3
4
5
2
3
4
5
The correct answer: A
Question 5:
Which of the following defines a function expression?
javascript
A) function expression() {}
B) const expression = function() {};
C) expression() {}
D) function: expression() {}
E) expression = () => {};
1
2
3
4
5
2
3
4
5
The correct answer: B
Question 6:
What does the following code output?
javascript
function myFunc() {
return;
}
console.log(myFunc());
1
2
3
4
2
3
4
javascript
A) undefined
B) null
C) ''
D) 0
E) Error
1
2
3
4
5
2
3
4
5
The correct answer: A
Question 7:
What does the term "hoisting" refer to in JavaScript functions?
javascript
A) Function declarations are moved to the top of their scope
B) Variables cannot be declared after they are used
C) Functions cannot be called before they are declared
D) Functions are automatically optimized by the engine
E) None of the above
1
2
3
4
5
2
3
4
5
The correct answer: A
Question 8:
What will the following code output?
javascript
let x = 10;
function test() {
let x = 20;
console.log(x);
}
test();
console.log(x);
1
2
3
4
5
6
7
2
3
4
5
6
7
javascript
A) 10
B) 20
C) 10, 20
D) 20, 10
E) undefined
1
2
3
4
5
2
3
4
5
The correct answer: D
Question 9:
Which of the following is a higher-order function?
javascript
A) function() {}
B) map()
C) forEach()
D) reduce()
E) All of the above
1
2
3
4
5
2
3
4
5
The correct answer: E
Question 10:
What is a closure in JavaScript?
javascript
A) A function that can access variables from its outer scope
B) A way to hide variables
C) A method of error handling
D) A way to create asynchronous functions
E) All of the above
1
2
3
4
5
2
3
4
5
The correct answer: A
Question 11:
What will the following code log to the console?
javascript
function outer() {
let count = 0;
return function inner() {
count++;
return count;
}
}
const counter = outer();
console.log(counter());
console.log(counter());
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
javascript
A) 0, 1
B) 1, 1
C) 1, 2
D) 0, 0
E) 2, 1
1
2
3
4
5
2
3
4
5
The correct answer: C
Question 12:
Which of the following correctly uses a callback function?
javascript
A) setTimeout(() => { console.log("Hello!"); }, 1000);
B) let result = add(2, 3);
C) console.log("Hello!");
D) function myFunc() {}
E) let x = 5;
1
2
3
4
5
2
3
4
5
The correct answer: A
Question 13:
What is the output of the following code?
javascript
function fetchData(callback) {
callback("Data received");
}
fetchData(data => console.log(data));
1
2
3
4
2
3
4
javascript
A) Data received
B) undefined
C) Error
D) Data
E) No output
1
2
3
4
5
2
3
4
5
The correct answer: A
Question 14:
What does the Promise
object represent?
javascript
A) An eventual completion or failure of an asynchronous operation
B) A synchronous operation
C) A function declaration
D) A variable scope
E) None of the above
1
2
3
4
5
2
3
4
5
The correct answer: A
Question 15:
How do you handle errors in asynchronous functions using Promises?
javascript
A) .catch()
B) try-catch
C) throw
D) console.error()
E) All of the above
1
2
3
4
5
2
3
4
5
The correct answer: A
Question 16:
What will the following code output?
javascript
async function myAsyncFunction() {
return "Hello, Async!";
}
myAsyncFunction().then(console.log);
1
2
3
4
2
3
4
javascript
A) Hello, Async!
B) Promise { 'Hello, Async!' }
C) Error
D) undefined
E) No output
1
2
3
4
5
2
3
4
5
The correct answer: A
Question 17:
What is the purpose of async/await
in JavaScript?
javascript
A) To make asynchronous code look synchronous
B) To define synchronous functions
C) To declare variables
D) To create loops
E) To return values
1
2
3
4
5
2
3
4
5
The correct answer: A
Question 18:
What will happen if you call a function before its declaration?
javascript
A) It will throw an error
B) It will return undefined
C) It will execute normally if it's a function declaration
D) It will execute normally if it's a function expression
E) None of the above
1
2
3
4
5
2
3
4
5
The correct answer: C
Question 19:
Which of the following is NOT a valid default parameter?
javascript
A) function greet(name = "Guest") {}
B) function add(a, b = 0) {}
C) function multiply(a, b = 1, c) {}
D) function log(message, level = "info") {}
E) function subtract(a, b = 0, c = 5) {}
1
2
3
4
5
2
3
4
5
The correct answer: C
Question 20:
What does the try...catch
statement do?
javascript
A) It allows you to handle errors gracefully
B) It stops the program execution
C) It throws errors
D) It declares a function
E) None of the above
1
2
3
4
5
2
3
4
5
The correct answer: A
Summary:
In this course, we explored the fundamental concepts of functions in JavaScript. We covered different types of functions, how to handle parameters and arguments, the mechanics of return values, scope, and hoisting. We also delved into higher-order functions, closures, callback functions, and the use of promises along with async/await for asynchronous programming.
The best practices for writing efficient and maintainable functions were highlighted, including naming conventions, keeping functions small, and proper documentation.
Functions are a core aspect of JavaScript that enable modular, reusable, and efficient code. Mastering functions will empower you to write better JavaScript and handle complex problems with ease.
Additional Resources:
- Functions - JavaScript - MDN Web Docs
- Functions - JavaScript - MDN Web Docs
- Functions in JavaScript - GeeksforGeeks
- JavaScript Functions 101: The Basics | Capital One
- JavaScript Functions - W3Schools
- JavaScript language overview - MDN Web Docs - Mozilla
- JavaScript Overview — Understanding Functions | by Vlad Antsitovich
- Introduction to JavaScript: Functions | by Mahendra Choudhary
- Functions | web.dev
- function - JavaScript - MDN Web Docs - Mozilla