JavaScript Functions
Functions are reusable blocks of code — write once, use endlessly. Think of them as recipes: define the steps once, then follow them every time you cook. A programmer who doesn't use functions is like someone reinventing every dish from scratch — exhausting and error-prone.
What Is a Function?
A function "packages" a piece of logic, gives it a name, and lets you call it whenever needed:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Calling Functions</title></head>
<body>
<div id="output"></div>
<script>
function sayHello() {
document.getElementById('output').textContent += 'Hello!\n';
}
sayHello();
sayHello();
</script>
</body>
</html>
Benefits of functions:
- Reusability: write once, call everywhere
- Encapsulation: hide complexity, expose only the interface
- Maintainability: change it in one place, every caller benefits
Function Declaration vs Function Expression
There are two main ways to create functions:
<script>
// Function declaration
function greet(name) {
return `Hello, ${name}!`;
}
// Function expression
let greet2 = function(name) {
return `Hello, ${name}!`;
};
</script>
Key difference: function declarations are hoisted — you can call them before they appear in the code. Function expressions are not hoisted; you must define them first.
<script>
// Function declaration: call before definition — works fine
hello(); // Runs without error
function hello() { console.log('hi'); }
// Function expression: call before definition — error
// hi(); // TypeError: hi is not a function
// let hi = function() { console.log('hi'); };
</script>
let variable before its declaration triggers a "temporal dead zone" (TDZ) error — not undefined. So always define function expressions before using them.
Parameters and Default Parameters
Functions accept external data through parameters:
<script>
function add(a, b) {
return a + b;
}
add(1, 2); // 3
</script>
Parameters you don't pass are undefined. ES6 introduced default parameters:
<script>
function greet(name, greeting = 'Hello') {
return `${greeting}, ${name}!`;
}
greet('Alice'); // 'Hello, Alice!'
greet('Alice', 'Hi'); // 'Hi, Alice!'
</script>
Return Values
return sends a result back to the caller and immediately stops the function:
<script>
function square(n) {
return n * n;
}
let result = square(5); // 25
</script>
A function without return (or with just return;) returns undefined.
<script>
function doNothing() {
// no return
}
doNothing(); // undefined
</script>
return causes automatic semicolon insertion, making it return undefined:
return // becomes: return; undefined
obj; // this line never executes
Fix: keep the return value on the same line, or wrap it in parentheses.
Arrow Functions (=>)
Arrow functions are a shorter syntax introduced in ES6:
<script>
// Regular function
let double = function(n) {
return n * 2;
};
// Arrow function
let double2 = (n) => n * 2;
// Multiple statements require braces and explicit return
let greet = (name) => {
let msg = `Hello, ${name}!`;
return msg;
};
</script>
Syntax rules:
- Single parameter: parentheses optional —
n => n * 2 - Zero or multiple parameters: parentheses required —
() => 'hi',(a, b) => a + b - Single-line expression: auto-returns; multi-line: needs
{}+return
Example: Basic Function Usage
<!DOCTYPE html>
<html>
<body>
<h2>Basic Function Usage</h2>
<div id="output"></div>
<script>
function add(a, b) {
return a + b;
}
function greet(name, greeting) {
if (greeting === undefined) greeting = 'Hello';
return greeting + ', ' + name + '!';
}
let multiply = (a, b) => a * b;
let square = n => n * n;
let html = '';
html += 'add(3, 5) = ' + add(3, 5) + '<br>';
html += 'add(10, 20) = ' + add(10, 20) + '<br>';
html += "greet('Alice') = " + greet('Alice') + '<br>';
html += "greet('Alice', 'Hi') = " + greet('Alice', 'Hi') + '<br>';
html += 'multiply(4, 6) = ' + multiply(4, 6) + '<br>';
html += 'square(7) = ' + square(7) + '<br>';
document.getElementById('output').innerHTML = html;
</script>
</body>
</html>
Example: Simple Calculator
<!DOCTYPE html>
<html>
<body>
<h2>Simple Calculator</h2>
<input type="number" id="numA" placeholder="Number 1">
<select id="op">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">×</option>
<option value="/">÷</option>
</select>
<input type="number" id="numB" placeholder="Number 2">
<button onclick="calc()">Calculate</button>
<p id="result"></p>
<script>
function calc() {
let a = Number(document.getElementById('numA').value);
let b = Number(document.getElementById('numB').value);
let op = document.getElementById('op').value;
let res;
switch (op) {
case '+': res = a + b; break;
case '-': res = a - b; break;
case '*': res = a * b; break;
case '/':
if (b === 0) {
document.getElementById('result').innerHTML = 'Cannot divide by zero!';
return;
}
res = a / b;
break;
}
document.getElementById('result').innerHTML =
a + ' ' + op + ' ' + b + ' = <strong>' + res + '</strong>';
}
</script>
</body>
</html>
Function Scope
Variables declared inside a function are local — they only exist within that function. This is scope:
<script>
function test() {
let x = 10; // local variable
const y = 20;
var z = 30;
}
test();
// console.log(x); // ReferenceError: x is not defined
</script>
Functions can access outer variables (the foundation of closures), but the outer code cannot access variables inside a function:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Function Scope</title></head>
<body>
<pre id="output"></pre>
<script>
let global = 'Global variable';
function show() {
let local = 'Local variable';
document.getElementById('output').textContent +=
'Inside function — global: ' + global + '\n' +
'Inside function — local: ' + local + '\n';
}
show();
document.getElementById('output').textContent +=
'Outside function — global: ' + global + '\n' +
'Outside function — local: not accessible (local variable)';
</script>
</body>
</html>
let/const/var creates a global variable — a common source of bugs. Always declare variables with let or const.
Example: Scope Demo
<!DOCTYPE html>
<html>
<body>
<h2>Function Scope</h2>
<div id="output"></div>
<script>
let outer = 'Outer variable';
function demo() {
let inner = 'Inner variable';
let html = '';
html += 'Inside function — outer: ' + outer + '<br>';
html += 'Inside function — inner: ' + inner + '<br>';
function nested() {
let deep = 'Nested variable';
html += 'Nested function — outer: ' + outer + '<br>';
html += 'Nested function — inner: ' + inner + '<br>';
html += 'Nested function — deep: ' + deep + '<br>';
}
nested();
return html;
}
let result = demo();
result += 'Outside function — outer: ' + outer + '<br>';
result += 'Outside function — inner: not accessible (local)';
document.getElementById('output').innerHTML = result;
</script>
</body>
</html>
Introduction to Callbacks
JavaScript lets you pass a function as an argument to another function — the passed-in function is called a callback:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Callbacks</title></head>
<body>
<pre id="output"></pre>
<script>
function processArray(arr, callback) {
for (let item of arr) {
callback(item);
}
}
let names = ['Alice', 'Bob', 'Charlie'];
processArray(names, function(name) {
document.getElementById('output').textContent += 'Hello, ' + name + '\n';
});
</script>
</body>
</html>
You've already used callbacks — the arguments to forEach, map, and filter are all callback functions:
<script>
// The anonymous function here is a callback
[1, 2, 3].forEach(function(n) {
console.log(n);
});
// Arrow functions make it more concise
[1, 2, 3].forEach(n => console.log(n));
</script>
Example: Callbacks in Action
<!DOCTYPE html>
<html>
<body>
<h2>Callback Functions</h2>
<div id="output"></div>
<script>
function processList(items, action) {
let results = [];
for (let item of items) {
results.push(action(item));
}
return results;
}
let nums = [1, 2, 3, 4, 5];
let doubled = processList(nums, n => n * 2);
let squared = processList(nums, n => n * n);
let labeled = processList(nums, n => 'Item ' + n);
let html = '';
html += 'Original: [' + nums.join(', ') + ']<br><br>';
html += '<strong>Callback: n => n * 2</strong><br>';
html += 'Result: [' + doubled.join(', ') + ']<br><br>';
html += '<strong>Callback: n => n * n</strong><br>';
html += 'Result: [' + squared.join(', ') + ']<br><br>';
html += '<strong>Callback: n => "Item " + n</strong><br>';
html += 'Result: [' + labeled.join(', ') + ']<br><br>';
html += '<strong>setTimeout callback (appears after 2 seconds):</strong><br>';
html += '<span id="timer">Waiting...</span>';
document.getElementById('output').innerHTML = html;
setTimeout(function() {
document.getElementById('timer').textContent = "Time's up! Callback executed.";
document.getElementById('timer').style.color = 'green';
}, 2000);
</script>
</body>
</html>
📖 Summary
- Function declarations are hoisted; function expressions are not — defining before use is safest
- Default parameters add flexibility; place them at the end of the parameter list
returnends the function and sends back a value; without it, the function returnsundefined- Arrow functions
(a, b) => a + bare shorthand — single-line auto-returns, multi-line needs{} - Variables declared inside a function are local and invisible outside
- Callbacks = passing a function as an argument — used by
forEach,setTimeout, and many more
❓ FAQ
this — they inherit it from the surrounding scope. When you need this to refer to the current object (in methods or event handlers), use a regular function. For simple utility functions, arrow syntax works great.function getInfo() { return [name, age]; } — then call with let [name, age] = getInfo().function createUser({ name, age, city }) {} — call it with createUser({ name: 'Alice', age: 20, city: 'NYC' }). Order doesn't matter, and it's much more readable.📝 Exercises
- Write a function
isEven(n)that returnstrueif a number is even,falseotherwise. Test it with multiple values on the page. - Write a function
formatPrice(price)that takes a number and returns a formatted price string (e.g.,formatPrice(9.9)returns"$9.90"). Use arrow function syntax. - Build a "greeting generator": use a callback function that takes an array of names and a greeting function, then display personalized greetings for each person on the page.



