JavaScript Functions
Functions are reusable blocks of code that perform specific tasks. They are fundamental to JavaScript and can be defined in multiple ways: declarations, expressions, and arrow functions.
Function Declaration
The traditional way to define a function using the function keyword:
// Function Declaration
function greet(name) {
return "Hello, " + name + "!";
}
// Can be called before declaration (hoisted)
sayHello(); // Works!
function sayHello() {
console.log("Hello!");
}
// Parameters and return value
function add(a, b) {
return a + b; // Returns the sum
}
const result = add(2, 3); // result = 5Function Expression
A function assigned to a variable:
// Function Expression
const greet = function(name) {
return "Hello, " + name + "!";
};
// Named function expression (useful for recursion/debugging)
const factorial = function fact(n) {
if (n <= 1) return 1;
return n * fact(n - 1);
};
// Cannot be called before definition
// multiply(2, 3); // Error!
const multiply = function(a, b) {
return a * b;
};Arrow Functions
A shorter syntax introduced in ES6. Arrow functions are ideal for callbacks and do not have their own this binding:
// Arrow Function (ES6)
const greet = (name) => {
return "Hello, " + name + "!";
};
// Short syntax (implicit return)
const add = (a, b) => a + b;
// Single parameter (parentheses optional)
const double = x => x * 2;
// No parameters (parentheses required)
const sayHi = () => "Hi!";
// Returning an object (wrap in parentheses)
const createUser = (name) => ({ name, id: Date.now() });
// Arrow functions and "this"
const obj = {
name: "Alice",
// Regular function - "this" is obj
greet: function() {
console.log("Hello, " + this.name);
},
// Arrow - "this" is inherited (not obj!)
greetArrow: () => {
console.log("Hello, " + this.name); // this.name is undefined
}
};this. Comparison
| Feature | Declaration | Expression | Arrow |
|---|---|---|---|
| Hoisted | |||
| Named | Optional | ||
| Own this | |||
| Can be constructor | |||
| arguments object |
The Return Statement
Use return to send a value back from a function and end execution:
// Explicit return
function add(a, b) {
return a + b; // Execution stops here
console.log("Never runs");
}
// No return = undefined
function noReturn() {
console.log("Hello");
// Implicitly returns undefined
}
// Early return for validation
function divide(a, b) {
if (b === 0) {
return "Error: Division by zero";
}
return a / b;
}
// Return multiple values (use object or array)
function getMinMax(arr) {
return {
min: Math.min(...arr),
max: Math.max(...arr)
};
}
const { min, max } = getMinMax([1, 5, 3, 9, 2]);Try It Yourself
Experiment with different function types:
// Function Declaration
function greet(name) {
return "Hello, " + name + "!";
}
console.log(greet("Alice"));
// Function Expression
const add = function(a, b) {
return a + b;
};
console.log("2 + 3 =", add(2, 3));
// Arrow Function
const multiply = (a, b) => a * b;
console.log("4 * 5 =", multiply(4, 5));
// Arrow function with block body
const divide = (a, b) => {
if (b === 0) return "Cannot divide by zero";
return a / b;
};
console.log("10 / 2 =", divide(10, 2));
// Function with default parameters
function greetWithDefault(name = "Guest") {
return "Welcome, " + name + "!";
}
console.log(greetWithDefault());
console.log(greetWithDefault("Bob"));Callback Functions
Functions can be passed as arguments to other functions. These are called callbacks:
// Functions as arguments (callbacks)
function processArray(arr, callback) {
const result = [];
for (const item of arr) {
result.push(callback(item));
}
return result;
}
// Using with different callbacks
const numbers = [1, 2, 3, 4, 5];
const doubled = processArray(numbers, x => x * 2);
console.log("Doubled:", doubled);
const squared = processArray(numbers, x => x * x);
console.log("Squared:", squared);
// Built-in array methods with callbacks
const filtered = numbers.filter(x => x > 2);
console.log("Filtered (>2):", filtered);
const sum = numbers.reduce((acc, x) => acc + x, 0);
console.log("Sum:", sum);
// setTimeout callback
console.log("Starting timer...");
setTimeout(() => {
console.log("Timer finished!");
}, 1000);Immediately Invoked Function Expression (IIFE)
A function that runs immediately after it is defined:
// Immediately Invoked Function Expression (IIFE)
(function() {
console.log("I run immediately!");
})();
// IIFE with arrow function
(() => {
console.log("Arrow IIFE!");
})();
// IIFE with parameters
(function(name) {
console.log("Hello, " + name);
})("Alice");
// Use case: Create private scope
const counter = (function() {
let count = 0; // Private variable
return {
increment: () => ++count,
decrement: () => --count,
get: () => count
};
})();
counter.increment(); // 1
counter.increment(); // 2
counter.get(); // 2Best Practices
calculateTotal, validateEmail, fetchUserData. Test Your Knowledge
Test Your Knowledge
5 questionsWhat is hoisting in relation to functions?
What does an arrow function NOT have?
What does a function return if there is no return statement?
Which syntax is correct for an arrow function with one parameter?
What is a callback function?
Practice Exercise
Function Composition
Create a compose function that takes multiple functions and returns a new function that applies them right-to-left.
// Challenge: Create a function that composes multiple functions
// compose(f, g, h)(x) should equal f(g(h(x)))
function compose(...functions) {
// TODO: Return a function that applies all functions right-to-left
}
// Test functions
const addOne = x => x + 1;
const double = x => x * 2;
const square = x => x * x;
// Test compose
const composed = compose(addOne, double, square);
console.log(composed(3)); // Should print 19: (3^2) * 2 + 1 = 9 * 2 + 1 = 19
const composed2 = compose(double, addOne);
console.log(composed2(5)); // Should print 12: (5 + 1) * 2 = 12
Frequently Asked Questions
When should I use arrow functions vs regular functions?
Use arrow functions for callbacks, array methods, and when you need to preserve this from the outer scope. Use regular functions for object methods and constructors where you need their own this.
What is a pure function?
A pure function always returns the same output for the same input and has no side effects (doesn't modify external state). Pure functions are easier to test, debug, and reason about.
Can I have a function inside another function?
Yes! These are called nested functions or inner functions. The inner function has access to the outer function's variables (closure). This is useful for creating private helper functions.
Summary
JavaScript has three ways to define functions:
- Declaration:
function name() {}- hoisted - Expression:
const name = function() {}- not hoisted - Arrow:
const name = () => {}- no own this
Key points:
- Functions can accept parameters and return values
- Arrow functions are great for callbacks but lack their own
this - Functions without
returnreturnundefined - Functions can be passed as arguments (callbacks)