JavaScript Functions
Functions are one of the fundamental building blocks in JavaScript. A function is a reusable block of code designed to perform a particular task. Functions help organize code, make it reusable, and improve maintainability.
Function Declarations
The most common way to define a function is using a function declaration:
function greet(name) {
return "Hello, " + name + "!";
}
// Calling the function
console.log(greet("John")); // Outputs: "Hello, John!"
Function declarations are hoisted, meaning they can be called before they are defined in the code.
Function Expressions
Another way to define a function is using a function expression:
// Anonymous function expression
const greet = function(name) {
return "Hello, " + name + "!";
};
// Named function expression
const sayHello = function sayHelloFunc(name) {
return "Hello, " + name + "!";
};
// Calling the functions
console.log(greet("John")); // Outputs: "Hello, John!"
console.log(sayHello("Jane")); // Outputs: "Hello, Jane!"
Unlike function declarations, function expressions are not hoisted. They must be defined before they are called.
Arrow Functions (ES6)
Arrow functions provide a more concise syntax for writing functions and lexically bind the this
value:
// Basic arrow function
const greet = (name) => {
return "Hello, " + name + "!";
};
// Simplified return (implicit return)
const greetSimple = name => "Hello, " + name + "!";
// Arrow function with no parameters
const sayHi = () => "Hi there!";
// Arrow function with multiple parameters
const introduce = (name, age) => `I'm ${name} and I'm ${age} years old.`;
// Calling the functions
console.log(greet("John")); // Outputs: "Hello, John!"
console.log(greetSimple("Jane")); // Outputs: "Hello, Jane!"
console.log(sayHi()); // Outputs: "Hi there!"
console.log(introduce("Alice", 30)); // Outputs: "I'm Alice and I'm 30 years old."
Note: Arrow functions don't have their own this
context. They inherit this
from the enclosing scope, which can be useful in certain situations like callbacks and methods.
Function Parameters
Default Parameters (ES6)
function greet(name = "Guest") {
return "Hello, " + name + "!";
}
console.log(greet()); // Outputs: "Hello, Guest!"
console.log(greet("John")); // Outputs: "Hello, John!"
Rest Parameters (ES6)
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2)); // Outputs: 3
console.log(sum(1, 2, 3, 4, 5)); // Outputs: 15
The arguments Object
function oldSchoolSum() {
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
console.log(oldSchoolSum(1, 2, 3, 4)); // Outputs: 10
Warning: The arguments
object is not available in arrow functions. Use rest parameters instead for modern code.
Return Values
Functions can return values using the return
statement:
function add(a, b) {
return a + b;
}
const result = add(5, 3);
console.log(result); // Outputs: 8
// Early return
function checkAge(age) {
if (age < 18) {
return "Too young";
}
return "Old enough";
}
// Function with no return statement (or just 'return;')
// implicitly returns undefined
function doSomething() {
console.log("Doing something...");
// No return statement
}
const value = doSomething();
console.log(value); // Outputs: undefined
Function Scope and Closures
Lexical Scope
function outer() {
const outerVar = "I'm from outer function";
function inner() {
const innerVar = "I'm from inner function";
console.log(outerVar); // Can access outerVar
}
inner();
// console.log(innerVar); // Error: innerVar is not defined
}
outer();
Closures
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // Outputs: 1
console.log(counter()); // Outputs: 2
console.log(counter()); // Outputs: 3
// Each counter is independent
const counter2 = createCounter();
console.log(counter2()); // Outputs: 1
Tip: Closures are powerful for creating private variables and maintaining state between function calls.
Immediately Invoked Function Expressions (IIFE)
An IIFE is a function that runs as soon as it is defined:
(function() {
console.log("This function runs immediately!");
})();
// With parameters
(function(name) {
console.log("Hello, " + name + "!");
})("John");
// Arrow function IIFE
(() => {
console.log("Arrow function IIFE");
})();
IIFEs are useful for creating private scopes and avoiding polluting the global namespace.
Higher-Order Functions
Higher-order functions are functions that take other functions as arguments or return functions:
// Function that takes a function as an argument
function executeOperation(operation, a, b) {
return operation(a, b);
}
// Functions to pass as arguments
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
console.log(executeOperation(add, 5, 3)); // Outputs: 8
console.log(executeOperation(multiply, 5, 3)); // Outputs: 15
// Function that returns a function
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // Outputs: 10
console.log(triple(5)); // Outputs: 15
Common Array Methods with Function Arguments
Many array methods in JavaScript take functions as arguments:
const numbers = [1, 2, 3, 4, 5];
// map - creates a new array by transforming each element
const doubled = numbers.map(num => num * 2);
console.log(doubled); // Outputs: [2, 4, 6, 8, 10]
// filter - creates a new array with elements that pass a test
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // Outputs: [2, 4]
// reduce - reduces the array to a single value
const sum = numbers.reduce((total, num) => total + num, 0);
console.log(sum); // Outputs: 15
// forEach - executes a function for each element
numbers.forEach(num => console.log(num)); // Outputs each number
Interactive Example: Function Calculator
Best Practices for Functions
- Single Responsibility: Each function should do one thing and do it well.
- Descriptive Names: Use clear, descriptive names that indicate what the function does.
- Keep Functions Small: Aim for functions that are short and focused.
- Limit Parameters: Try to keep the number of parameters to a minimum (ideally 3 or fewer).
- Use Default Parameters: Provide default values for parameters when appropriate.
- Return Early: Use early returns to avoid deep nesting and improve readability.
- Avoid Side Effects: Functions should ideally not modify variables outside their scope.
- Consistent Return Types: A function should return consistent types of values.
Next Steps
Now that you understand JavaScript functions, you can explore:
- Object-oriented programming with JavaScript
- Functional programming concepts
- Asynchronous functions with Promises and async/await
- Advanced patterns like currying and composition