Learn JavaScript functions - declarations, expressions, arrow functions, parameters, scope, closures, and callbacks.
Functions
A function is a reusable block of code that performs a specific task. Functions are the fundamental building block of any JavaScript program.
Function declarations
The classic way to define a function:
Result:
Anatomy:
function- the keywordgreet- the function name(name)- the parameter listreturn- sends a value back to the callergreet("Ada")- calling the function with the argument"Ada"
Functions without a return value
If a function does not return anything, it returns undefined:
Result:
Function expressions
You can also assign a function to a variable:
Result:
The difference from a declaration: function expressions are not hoisted (explained below).
Arrow functions
A shorter syntax introduced in ES6:
Result:
Implicit return
If the body is a single expression, you can omit the braces and return:
Result:
Single parameter shorthand
With exactly one parameter, you can omit the parentheses:
Result:
When to use which
Arrow functions have a different this behavior compared to regular functions. This matters when working with objects (
covered in the Objects chapter). For now, arrow functions are your go-to for short, simple functions.
Parameters and arguments
Parameters are the names listed in the function definition. Arguments are the actual values passed to the function.
Default parameters
Provide fallback values for missing arguments:
Result:
Rest parameters
Collect any number of arguments into an array:
Result:
The rest parameter must be the last parameter:
Result:
Return values
A function can return any value - numbers, strings, booleans, arrays, objects, even other functions:
Result:
Early return
return exits the function immediately. Use it to handle edge cases first:
Result:
This pattern - handling errors early and returning - is called a guard clause. It keeps your code flat instead of deeply nested.
Scope
Scope determines where a variable is accessible.
Block scope (let and const)
Variables declared with let or const are confined to the nearest {} block:
Result:
Function scope
Variables declared inside a function are not accessible outside it:
Result:
Global scope
Variables declared outside any function or block are global - accessible everywhere:
Result:
Minimize global variables. They can be modified from anywhere, making bugs hard to track.
Scope chain
Inner functions can access variables from outer functions:
Result:
Hoisting
Function declarations are hoisted - you can call them before they appear in the code:
Result:
Function expressions and arrow functions are NOT hoisted:
Result:
var declarations are hoisted too, but only the declaration - not the assignment. This is another reason to avoid
var.
Closures
A closure is a function that remembers the variables from the scope where it was created, even after that scope has finished executing:
Result:
The inner function "closes over" the count variable. Each call to createCounter() creates a new, independent
counter:
Result:
Closures are fundamental to JavaScript. They power patterns like data privacy, factory functions, and event handlers.
Practical closure: private state
Result:
Callbacks
A callback is a function passed as an argument to another function:
Result:
Callbacks are commonly used with array methods (next chapter) and asynchronous operations.
Anonymous callbacks
You can pass an arrow function directly instead of defining a named function:
Result:
Higher-order functions
A higher-order function is a function that takes a function as an argument or returns a function. You have already seen both:
doTasktakes a callback - higher-order (takes a function)createCounterreturns a function - higher-order (returns a function)
Result:
Higher-order functions are everywhere in JavaScript - array methods like map, filter, and reduce (covered in the
next chapter) are all higher-order functions.
Pure functions
A pure function always returns the same output for the same input and has no side effects:
Result:
Prefer pure functions when possible - they are easier to test, debug, and reason about.
Immediately Invoked Function Expressions (IIFE)
A function that runs immediately after it is defined:
Result:
IIFEs were historically used to create private scope before let/const and modules existed. You will see them in
older code.
Summary
- Function declarations are hoisted; expressions and arrow functions are not.
- Arrow functions
=>provide concise syntax with implicit return for single expressions. - Default parameters provide fallback values; rest parameters collect extra arguments into an array.
- Guard clauses (early returns) keep code flat and readable.
- Scope determines variable accessibility: block, function, or global.
- Closures let inner functions remember outer variables - key for private state and factories.
- Callbacks are functions passed to other functions - foundational to async JavaScript.
- Pure functions are predictable and testable - prefer them when possible.
Next up: Arrays - ordered collections of data and the powerful methods to work with them.