README
5.1 Function Declarations
Overview
Functions are the fundamental building blocks of JavaScript applications. A function declaration is one of the primary ways to define a reusable block of code that performs a specific task. Function declarations are hoisted, meaning they can be called before they appear in the code.
Table of Contents
- ā¢What is a Function?
- ā¢Function Declaration Syntax
- ā¢Calling Functions
- ā¢Parameters and Arguments
- ā¢Return Statement
- ā¢Hoisting
- ā¢Function Naming Conventions
- ā¢Scope Inside Functions
- ā¢Function as First-Class Citizens
- ā¢Best Practices
What is a Function?
A function is a reusable block of code designed to perform a particular task.
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Function Anatomy ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā ā
ā function greet(name) { ā
ā āāāāāāāā āāāāā āāāā ā
ā keyword name parameters ā
ā ā
ā return "Hello, " + name; ā
ā āāāāāā āāāāāāāāāāāāāāāā ā
ā return return value ā
ā } ā
ā ā
ā greet("World"); // Call the function ā
ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Why Use Functions?
| Benefit | Description |
|---|---|
| Reusability | Write once, use many times |
| Modularity | Break code into manageable pieces |
| Abstraction | Hide complexity behind simple interfaces |
| Maintainability | Easier to update and debug |
| Testing | Functions can be tested in isolation |
Function Declaration Syntax
Basic Syntax
function functionName(parameters) {
// Function body
// Code to execute
return value; // Optional
}
Examples
// Simple function with no parameters
function sayHello() {
console.log('Hello!');
}
// Function with one parameter
function greet(name) {
console.log('Hello, ' + name + '!');
}
// Function with multiple parameters
function add(a, b) {
return a + b;
}
// Function with no return (returns undefined)
function logMessage(message) {
console.log(message);
}
Calling Functions
To execute a function, you call (or invoke) it using its name followed by parentheses.
// Define
function greet(name) {
return 'Hello, ' + name;
}
// Call
greet('Alice'); // "Hello, Alice"
greet('Bob'); // "Hello, Bob"
// Store result
const message = greet('Charlie');
console.log(message); // "Hello, Charlie"
// Use in expressions
console.log(greet('Dave').toUpperCase()); // "HELLO, DAVE"
Function Call vs Function Reference
function sayHi() {
return 'Hi!';
}
sayHi(); // "Hi!" - Calls the function
sayHi; // [Function: sayHi] - Reference to function
Parameters and Arguments
Parameters
Variables listed in the function definition.
Arguments
Actual values passed when calling the function.
function multiply(a, b) {
// a, b are parameters
return a * b;
}
multiply(3, 4); // 3, 4 are arguments
Default Parameters
function greet(name = 'Guest') {
return 'Hello, ' + name;
}
greet(); // "Hello, Guest"
greet('Alice'); // "Hello, Alice"
Multiple Parameters
function createUser(name, age, city = 'Unknown') {
return {
name: name,
age: age,
city: city,
};
}
createUser('John', 25, 'NYC');
createUser('Jane', 30); // city defaults to "Unknown"
Rest Parameters
function sum(...numbers) {
let total = 0;
for (const num of numbers) {
total += num;
}
return total;
}
sum(1, 2, 3); // 6
sum(1, 2, 3, 4, 5); // 15
Return Statement
The return statement specifies the value returned by the function.
// With return
function square(x) {
return x * x;
}
console.log(square(5)); // 25
// Without return (returns undefined)
function log(message) {
console.log(message);
}
console.log(log('Hi')); // undefined
Early Return
function absoluteValue(num) {
if (num < 0) {
return -num; // Early return
}
return num;
}
// Guard clause pattern
function processUser(user) {
if (!user) {
return null; // Guard clause
}
// Main logic
return { ...user, processed: true };
}
Returning Multiple Values
// Return an array
function minMax(numbers) {
return [Math.min(...numbers), Math.max(...numbers)];
}
const [min, max] = minMax([3, 1, 4, 1, 5, 9]);
// Return an object
function getUserInfo() {
return {
name: 'Alice',
age: 25,
email: 'alice@example.com',
};
}
const { name, email } = getUserInfo();
Hoisting
Function declarations are hoisted to the top of their scope, meaning you can call them before they appear in the code.
// This works!
greet('Alice'); // "Hello, Alice"
function greet(name) {
console.log('Hello, ' + name);
}
Hoisting Visualization
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Hoisting Process ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā ā
ā What you write: What JavaScript sees: ā
ā āāāāāāāāāāāāāā āāāāāāāāāāāāāāāāāāāā ā
ā ā
ā sayHi(); function sayHi() { ā
ā return "Hi!"; ā
ā function sayHi() { } ā
ā return "Hi!"; ā
ā } sayHi(); ā
ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Hoisting vs Function Expressions
// Function declaration - hoisted
greet(); // Works!
function greet() {
console.log('Hi');
}
// Function expression - NOT hoisted
// sayBye(); // Error: sayBye is not a function
const sayBye = function () {
console.log('Bye');
};
sayBye(); // Works after definition
Function Naming Conventions
Best Practices
| Pattern | Usage | Example |
|---|---|---|
| Verb + Noun | Actions | getUserData(), calculateTotal() |
| is/has/can | Boolean returns | isValid(), hasPermission() |
| get/set | Getters/Setters | getName(), setAge() |
| handle/on | Event handlers | handleClick(), onSubmit() |
| create/build | Factory functions | createUser(), buildConfig() |
| validate/check | Validation | validateEmail(), checkInput() |
Examples
// Action functions
function fetchUserData(userId) {}
function sendEmail(to, subject, body) {}
function calculateTax(amount, rate) {}
// Boolean functions
function isValidEmail(email) {
return email.includes('@');
}
function hasPermission(user, action) {
return user.permissions.includes(action);
}
// Getter/Setter style
function getUserName(user) {
return user.firstName + ' ' + user.lastName;
}
// Event handlers
function handleButtonClick(event) {}
function onFormSubmit(data) {}
Scope Inside Functions
Functions create their own scope. Variables declared inside are not accessible outside.
function createGreeting() {
const greeting = 'Hello'; // Local variable
return greeting;
}
createGreeting();
// console.log(greeting); // Error: greeting is not defined
Accessing Outer Scope (Closure)
const prefix = 'Mr. ';
function greet(name) {
// Can access prefix from outer scope
return prefix + name;
}
greet('Smith'); // "Mr. Smith"
Parameter Scope
function example(x) {
console.log(x); // Parameter is in local scope
const x = 10; // Error: x already declared
}
Functions as First-Class Citizens
In JavaScript, functions are values. They can be:
1. Assigned to Variables
const myFunc = function greet() {
return 'Hi';
};
2. Passed as Arguments
function executeCallback(callback) {
return callback();
}
function sayHello() {
return 'Hello!';
}
executeCallback(sayHello); // "Hello!"
3. Returned from Functions
function createMultiplier(factor) {
return function (number) {
return number * factor;
};
}
const double = createMultiplier(2);
double(5); // 10
4. Stored in Data Structures
const operations = {
add: function (a, b) {
return a + b;
},
subtract: function (a, b) {
return a - b;
},
};
operations.add(5, 3); // 8
operations.subtract(5, 3); // 2
Best Practices
1. Single Responsibility
// ā Does too much
function processOrder(order) {
// validate
// save to database
// send email
// update inventory
}
// ā
Single purpose
function validateOrder(order) {}
function saveOrder(order) {}
function sendConfirmation(order) {}
function updateInventory(order) {}
2. Keep Functions Small
// ā Too long
function doEverything() {
// 100+ lines of code
}
// ā
Small, focused functions
function step1() {}
function step2() {}
function step3() {}
3. Use Descriptive Names
// ā Unclear
function proc(d) {}
function x(a, b) {}
// ā
Descriptive
function processUserData(data) {}
function calculateTotal(items, taxRate) {}
4. Limit Parameters
// ā Too many parameters
function createUser(name, age, email, address, phone, role) {}
// ā
Use an options object
function createUser(options) {
const { name, age, email, address, phone, role } = options;
}
// ā
Or destructuring in parameters
function createUser({
name,
age,
email,
address = '',
phone = '',
role = 'user',
}) {}
5. Pure Functions When Possible
// ā Impure - modifies external state
let total = 0;
function addToTotal(amount) {
total += amount;
}
// ā
Pure - no side effects
function add(a, b) {
return a + b;
}
6. Early Returns for Readability
// ā Nested conditionals
function getDiscount(user) {
if (user) {
if (user.isPremium) {
if (user.yearsActive > 5) {
return 0.3;
} else {
return 0.2;
}
} else {
return 0.1;
}
}
return 0;
}
// ā
Early returns
function getDiscount(user) {
if (!user) return 0;
if (!user.isPremium) return 0.1;
if (user.yearsActive > 5) return 0.3;
return 0.2;
}
Summary
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Function Declarations Quick Reference ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā ā
ā // Basic syntax ā
ā function name(params) { ā
ā return value; ā
ā } ā
ā ā
ā // Key features: ā
ā ⢠Hoisted (can call before definition) ā
ā ⢠Create own scope ā
ā ⢠First-class citizens (values) ā
ā ⢠Can have default parameters ā
ā ⢠Can use rest parameters (...args) ā
ā ā
ā // Naming conventions: ā
ā ⢠verb + noun: calculateTotal() ā
ā ⢠is/has: isValid(), hasItems() ā
ā ⢠get/set: getName(), setAge() ā
ā ⢠handle/on: handleClick() ā
ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Next Steps
- ā¢Practice with the examples in
examples.js - ā¢Complete the exercises in
exercises.js - ā¢Learn about function expressions in the next topic
- ā¢Explore arrow functions and their syntax