03 / 20 · Day 1
Day 1 · Concept 03

Functions

Three syntaxes: function declarations, function expressions, arrow functions. They behave almost the same. The differences — hoisting, this, arguments — matter occasionally and bite you when they do.


1 · The three forms

js functions.js
// 1. Declaration — hoisted, named
function add(a, b) { return a + b; }

// 2. Expression — not hoisted, can be anonymous
const sub = function(a, b) { return a - b; };

// 3. Arrow — short, lexical this, no arguments
const mul = (a, b) => a * b;
const sq = x => x * x;          // single arg: parens optional
const greet = () => "hi";        // no args: parens required

console.log(add(2, 3), sub(5, 1), mul(4, 5), sq(7), greet());

2 · Default and rest parameters

js params.js
function greet(name = "world", greeting = "Hello") {
    return `${greeting}, ${name}!`;
}

console.log(greet());              // "Hello, world!"
console.log(greet("Alice"));        // "Hello, Alice!"
console.log(greet("Bob", "Hi"));    // "Hi, Bob!"

// Rest — collect remaining args
function sum(...nums) {
    return nums.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4));      // 10

3 · First-class functions

js first-class.js
// Pass functions as arguments
const apply = (fn, x) => fn(x);
console.log(apply(x => x * 2, 5));   // 10

// Return functions from functions (closures)
const multiplyBy = n => x => x * n;
const triple = multiplyBy(3);
console.log(triple(4));               // 12

// Store in arrays and objects
const ops = {
    add: (a, b) => a + b,
    sub: (a, b) => a - b,
};
console.log(ops.add(2, 3));          // 5

4 · Arrow vs function — the differences

Featurefunctionarrow
Has its own thisYesNo (lexical)
Has argumentsYesNo (use ...args)
HoistedIf declaredNo
Usable as constructor (new)YesNo
Has prototypeYesNo
The rule. Use arrows for callbacks and short helpers. Use function when you need this binding, arguments, or method definitions on prototypes / classes.

5 · Common mistakes

  • Arrow function method on an object. obj.greet = () => this.namethis isn't obj; it's the enclosing scope.
  • Forgetting return in a multi-statement arrow: x => { x * 2 } returns undefined. Use x => x * 2 or add return.
  • Mutating default param. function f(arr = []) — every call gets a fresh [], unlike Python's gotcha.

6 · When it clicks

  • Arrows for callbacks; named functions for top-level definitions.
  • You reach for ...rest and default params over conditional logic.
  • You know exactly when arrows save you from a this bug — and when they cause one.
Found this useful?