Home/Learn/JavaScript & TypeScript/Functions — Declarations, Expressions, Arrows, Defaults

Functions — Declarations, Expressions, Arrows, Defaults

Beginner
Language Core

Functions are values: assignable, passable, returnable. The forms differ in hoisting, in whether they have `this` and `arguments`, and in whether they can be used as constructors.

Overview

Treating functions as values is the foundation of everything idiomatic in JavaScript — callbacks, higher-order functions, the entire array API, React components. The forms look interchangeable but are not. Declarations hoist and can be called before they appear. Expressions do not. Arrows are shorter but deliberately lack this, arguments, and the ability to be called with new. Choosing correctly is mostly about whether the function needs its own this.

The Forms

Three ways to write a function, with real differences.

Three forms, three behaviours
// Declaration — hoisted, callable before its definition
function add(a, b) { return a + b }

// Expression — not hoisted; the variable follows normal TDZ rules
const sub = function (a, b) { return a - b }

// Arrow — no own this/arguments, cannot be newed
const mul = (a, b) => a * b
const square = n => n * n              // one param, parens optional
const make = () => ({ ok: true })      // object literal needs parens

// Arrows cannot be constructors:
const Bad = () => {}
new Bad()          // TypeError: Bad is not a constructor

Parameters

Defaults, rest and destructuring in the signature remove most argument-handling boilerplate.

Defaults, rest, destructured options
// Defaults — evaluated at call time, left to right
function paginate(page = 1, size = 20) { ... }
paginate(undefined, 50)      // page falls back to 1

// Rest — a real array, unlike arguments
function sum(...numbers) {
  return numbers.reduce((a, b) => a + b, 0)
}
sum(1, 2, 3)                 // 6

// Destructured params with defaults — the common options-object shape
function createUser({ name, role = 'student', active = true } = {}) {
  ...
}
createUser({ name: 'Asha' })
createUser()                 // the = {} makes this safe

Functions as Values

Passing and returning functions is not an advanced technique here — it is the normal way to write code.

Higher-order functions and composition
// Higher-order: takes a function
const byPrice = (a, b) => a.price - b.price
products.sort(byPrice)

// Returns a function
const withPrefix = prefix => msg => `[${prefix}] ${msg}`
const logError = withPrefix('ERROR')
logError('payment failed')      // '[ERROR] payment failed'

// Composition
const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x)
const slugify = pipe(
  s => s.toLowerCase(),
  s => s.trim(),
  s => s.replace(/\s+/g, '-'),
)
slugify('  Hello World ')       // 'hello-world'

Key Points to Remember

  • 1Function declarations hoist and are callable before their definition; expressions and arrows are not
  • 2Arrow functions have no own this, no arguments object, and cannot be called with new
  • 3Rest parameters give a real array; the old arguments object is array-like but not an array
  • 4A destructured parameter with `= {}` lets the caller omit the options object entirely
  • 5Functions are values — passing and returning them is ordinary JavaScript, not an advanced pattern

Interview Questions

Sign in to ask Aria
1

What is the difference between a function declaration and a function expression?

Easy
2

Name three things an arrow function cannot do that a regular function can.

Medium
3

Implement a `pipe` function that composes any number of functions left to right.

Medium

Ask Aria about Functions — Declarations, Expressions, Arrows, Defaults

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…