Functions and closures
Arrow functions, parameters, functions as values, closures.
Updated
What a function is
A function is a named block of code that you write once and run as many times as you want. It receives data (parameters), does something with it and, optionally, gives back a result (return).
Think of it as a recipe: the recipe (the function) is written once; every time you cook (call the function) you can use different ingredients (arguments).
function add(a, b) { // a, b = parameters (the required ingredients)
return a + b // the result
}
add(2, 3) // 5 — 2 and 3 = arguments (the actual ingredients)
add(10, 20) // 30Two different moments you need to be aware of:
| Definition | Call | |
|---|---|---|
| Code | function add(a, b) { ... } |
add(2, 3) |
| What happens | JS remembers the recipe, doesn't run it | JS runs the function body |
| How many times | once | as many as you want |
Why functions exist
- Reuse — you don't copy the same code into 10 places.
- A name —
calculateTotal(cart)says what it does; 15 lines of math don't. - Isolation — the variables inside the function don't mix with the rest of the code.
- Testing — a small function with clear input and output is easy to test.
Parameters and return
function greet(name = 'anonymous') { // default value
return `Hello, ${name}`
}
greet() // 'Hello, anonymous'
greet('Ana') // 'Hello, Ana'returnstops the function and gives back the result. Nothing after it runs.- Without
return, the function returnsundefined. - Missing parameters are
undefined(unless they have a default value).
Rest parameters and destructuring
const total = (...nums) => nums.reduce((s, n) => s + n, 0) // any number of arguments → an array
total(1, 2, 3) // 6
function createUser({ name, role = 'user' }) { // you receive an object, you pull out the fields
return { name, role }
}
createUser({ name: 'Ana' })More than 3 parameters? Switch to a single object — the order no longer matters and the call reads by itself.
Kinds of functions
1. Function declaration
function sum(a, b) {
return a + b
}2. Function expression
const sum = function (a, b) {
return a + b
}3. Arrow function
const sum = (a, b) => a + b // implicit return, a single expression
const square = x => x * x // one parameter — no parentheses
const getUser = () => ({ id: 1 }) // returning an object — add parentheses
const log = msg => { // several lines — braces + an explicit return
console.log(msg)
}4. Method (a function inside an object or class)
const cart = {
items: [],
add(item) { this.items.push(item) },
}5. Async function
async function loadUser(id) {
const res = await fetch(`/api/users/${id}`)
return res.json()
}It always returns a Promise — see Async.
The differences that matter
| Declaration | Expression | Arrow | Method | |
|---|---|---|---|---|
| Hoisting — you can call it before the line where it's written | yes | no | no | — |
Its own this |
yes (depends on the call) | yes | no — takes this from outside |
yes = the object |
arguments |
yes | yes | no | yes |
Can be used with new |
yes | yes | no | no |
| Implicit return | no | no | yes (one expression) | no |
Which one to use when
| Situation | The choice |
|---|---|
| a module's main function, a utility, a React component | declaration (function Card() {}) — reads clearly, has hoisting |
callbacks: map, filter, onClick, setTimeout, then |
arrow — short and keeps the outer this |
| small functions stored in variables, passed around as values | arrow |
behavior of an object / class that uses this |
method |
anything that uses await |
async (in any form) |
| a classic function expression | rare today — arrows replaced it |
Functions are values
In JS functions are first-class: you can put them in variables, pass them as arguments, return them from other functions.
const shout = text => text.toUpperCase()
['a', 'b'].map(shout) // passed as an argument → ['A', 'B']
const multiplier = factor => x => x * factor // returns a function
const double = multiplier(2)
double(5) // 10A function that receives or returns functions is called a higher-order function (map, filter, addEventListener).
Closure
A function remembers the variables from the place where it was created, even after that place has "finished". That's a closure.
function createCounter() {
let n = 0 // keeps living, "closed" inside the returned function
return () => ++n
}
const next = createCounter()
next() // 1
next() // 2 — n was remembered
const other = createCounter()
other() // 1 — every call creates a new nClosures are the basis of useState, React event handlers, debounce, modules.
Pure functions
A function is pure if:
- for the same input it always gives the same output;
- it has no side effects (doesn't change outside variables, doesn't make requests, doesn't write to the DOM).
const withVat = price => price * 1.19 // ✓ pure
let total = 0
const addToTotal = price => { total += price } // ✗ changes something outsideReact components must be pure. So should business logic — it's trivial to test.
Common mistakes
- Forgetting
return(especially in functions with braces) →undefined. - An arrow that returns an object without parentheses:
() => { id: 1 }returnsundefined. - Calling instead of passing:
onClick={save()}runs immediately; correct isonClick={save}oronClick={() => save(id)}.
Summary
- A function = named code, defined once, called any number of times; parameters → return.
- Declarations for main functions, arrows for callbacks, methods for objects.
- Functions are values; a closure = the function remembers where it was created.