Function Declaration
A function declaration uses the function keyword followed by a name, parameters, and a body. It is the most traditional way to define a function in JavaScript.
// Declare a function
function greet(name) {
return "Hello, " + name + "!";
}
// Call (invoke) it
console.log(greet("Alice")); // Hello, Alice!
console.log(greet("Bob")); // Hello, Bob!
// Function with no parameters
function sayHi() {
console.log("Hi there!");
}
sayHi();
Naming Conventions
- Use camelCase:
calculateTotal,getUserName - Start with a verb that describes what the function does:
get,set,calculate,validate,create,handle - Be specific:
getUserAgeis better thangetAgeordoStuff - Boolean-returning functions: prefix with
is,has,can:isValid,hasPermission
Function Expression
A function expression assigns a function to a variable. The function may be named or anonymous.
// Anonymous function expression
const square = function(n) {
return n * n;
};
console.log(square(5)); // 25
// Named function expression (name only visible inside body)
const factorial = function fact(n) {
if (n <= 1) return 1;
return n * fact(n - 1); // Can call fact() recursively here
};
console.log(factorial(5)); // 120
// Passed directly as an argument
setTimeout(function() {
console.log("Runs after 0ms");
}, 0);
Function Hoisting
JavaScript hoists function declarations to the top of their scope before execution. This means you can call a declared function before it appears in the source code. Function expressions are NOT hoisted in the same way.
// Call BEFORE the declaration β works because of hoisting
console.log(add(2, 3)); // 5
function add(a, b) {
return a + b;
}
// Function expression β NOT hoisted
try {
console.log(multiply(2, 3)); // Error!
} catch (e) {
console.log(e.message); // Cannot access 'multiply' before initialization
}
const multiply = function(a, b) {
return a * b;
};
During the creation phase, the JavaScript engine scans the code and registers all function declarations (and var declarations) before running any code. Only function declarations are fully hoisted β their name and body. var declarations are hoisted but initialized to undefined. let/const are hoisted but not initialized (Temporal Dead Zone).
IIFE β Immediately Invoked Function Expression
An IIFE runs immediately after it is defined. It creates a private scope and is used to avoid polluting the global namespace.
// Basic IIFE
(function() {
const secret = "I'm private!";
console.log("IIFE ran: " + secret);
})();
// Arrow function IIFE
(() => {
console.log("Arrow IIFE ran");
})();
// IIFE with parameters
const result = (function(a, b) {
return a + b;
})(10, 20);
console.log("IIFE result: " + result); // 30
// Variables inside IIFE don't leak out
try {
console.log(secret); // ReferenceError
} catch(e) {
console.log("Cannot access 'secret' outside IIFE");
}
Functions as First-Class Citizens
In JavaScript, functions are values β they can be assigned to variables, stored in arrays/objects, passed as arguments, and returned from other functions.
// Assign to variable
const greet = function(name) { return "Hi, " + name; };
// Store in object (method)
const math = {
add: function(a, b) { return a + b; },
subtract: (a, b) => a - b,
};
console.log(math.add(3, 4)); // 7
console.log(math.subtract(10, 3)); // 7
// Store in array
const operations = [
(x) => x * 2,
(x) => x + 10,
(x) => x ** 2,
];
console.log(operations[0](5)); // 10
console.log(operations[1](5)); // 15
console.log(operations[2](5)); // 25
// Pass as argument (callback)
function applyTwice(fn, value) {
return fn(fn(value));
}
console.log(applyTwice(x => x * 2, 3)); // 12
Functions vs Methods
A method is simply a function stored as a property of an object. The distinction is about context and calling syntax, not underlying mechanics.
// Standalone function
function describe(name, age) {
return name + " is " + age + " years old.";
}
// Same logic as a method
const person = {
name: "Alice",
age: 30,
describe: function() {
return this.name + " is " + this.age + " years old.";
}
};
console.log(describe("Bob", 25)); // Bob is 25 years old.
console.log(person.describe()); // Alice is 30 years old.
Default Parameters (ES6+)
// Default parameter values
function greetUser(name = "Stranger", greeting = "Hello") {
return greeting + ", " + name + "!";
}
console.log(greetUser()); // Hello, Stranger!
console.log(greetUser("Alice")); // Hello, Alice!
console.log(greetUser("Bob", "Hey")); // Hey, Bob!
// Default can reference earlier params
function createBadge(name, role = "member", prefix = role.toUpperCase()) {
return `[${prefix}] ${name}`;
}
console.log(createBadge("Alice", "admin")); // [ADMIN] Alice
Rest Parameters β Quick Intro
The ...rest syntax collects any number of extra arguments into an array. Full details are in the next lesson.
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5)); // 15
console.log(sum(10)); // 10
Recursion β A Brief Introduction
A function that calls itself is recursive. Every recursion needs a base case to stop, otherwise it creates infinite recursion and a stack overflow.
function factorial(n) {
if (n <= 1) return 1; // Base case
return n * factorial(n - 1); // Recursive case
}
console.log(factorial(5)); // 120 (5*4*3*2*1)
console.log(factorial(0)); // 1
ποΈ Practical Exercise
Create these functions:
- A declared function
celsiusToFahrenheit(c)β formula:(c * 9/5) + 32 - A function expression
capitalizethat capitalizes the first letter of a string - An IIFE that initializes an app counter starting at 100 and logs it
Verify that calling celsiusToFahrenheit before its declaration works (hoisting demo).
π₯ Challenge Exercise
Build a memoize(fn) function that wraps any function and caches its results. When called with the same arguments again, return the cached result without re-executing fn. Test it with the recursive factorial to demonstrate the speedup for repeated calls.
π Summary
- Function declarations are hoisted β callable before their definition in source code.
- Function expressions (and arrow functions) are NOT hoisted β must be defined first.
- IIFEs run immediately, creating private scope without polluting globals.
- Functions are first-class values β assignable, passable, returnable.
- Default parameters (ES6) eliminate the need for manual
|| defaultpatterns. - Rest parameters collect extra arguments into an array.
Interview Questions
- What is the difference between a function declaration and a function expression?
- What is function hoisting and how does it differ for declarations vs expressions?
- What is an IIFE and why would you use one?
- What does it mean for functions to be "first-class citizens" in JavaScript?
- What is the difference between a function and a method?
Frequently Asked Questions
Yes. If a function has no return statement (or a bare return;), it implicitly returns undefined. This is fine for functions whose purpose is side effects (logging, modifying DOM, etc.).
There is no hard limit (it's engine-dependent, typically thousands), but more than 3β4 parameters is a code smell. Use an options object instead: function create({ name, age, role }).
Parameters are the variable names listed in the function definition: function greet(name). Arguments are the actual values passed when calling the function: greet("Alice"). "Alice" is the argument; name is the parameter.