[2026] JavaScript Functions | Declarations, Arrows, Callbacks, and Closures

[2026] JavaScript Functions | Declarations, Arrows, Callbacks, and Closures

이 글의 핵심

JavaScript functions tutorial: declarations vs expressions, arrow functions, higher-order functions, closures, this, and callbacks—with patterns for real code.

Introduction

What is a function?

A function is a block of code that performs a task. In JavaScript, functions are first-class values: you can assign them to variables, pass them as arguments, and return them from other functions.

1. Ways to define functions

Function declaration

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

function add(a, b) {
    return a + b;
}
console.log(add(10, 20));  // 30
greet();  // hoisted
function greet() {
    console.log("Hello!");
}

Function expression

아래 코드는 javascript를 사용한 구현 예제입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

const subtract = function(a, b) {
    return a - b;
};
const factorial = function fact(n) {
    if (n <= 1) return 1;
    return n * fact(n - 1);
};
// multiply();  // ReferenceError if called before assignment
const multiply = function(a, b) {
    return a * b;
};

Arrow functions (ES6+)

다음은 javascript를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

const add = (a, b) => {
    return a + b;
};
const add = (a, b) => a + b;
const square = x => x * x;
const greet = () => console.log("Hello!");
const makePerson = (name, age) => ({ name, age });
console.log(makePerson("Alice", 25));
const complexFunc = (a, b) => {
    const sum = a + b;
    const product = a * b;
    return { sum, product };
};

Arrow function notes:

  1. Concise syntax
  2. Lexical this (inherits from enclosing scope)
  3. No arguments object—use rest parameters (...args)
  4. Not constructible—cannot use new When to use them: array callbacks, short utilities, when lexical this is what you want.

Comparison

DeclarationExpressionArrow
HoistingYesNo*No*
thisdynamicdynamiclexical
argumentsyesyesno
newyesyesno
* Assignments are not hoisted like declarations.

2. Parameters and return values

Default parameters

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

function greet(name = "guest") {
    return `Hello, ${name}!`;
}
function createArray(length = 10, fill = 0) {
    return Array(length).fill(fill);
}

Rest parameters

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

function sum(...numbers) {
    return numbers.reduce((acc, num) => acc + num, 0);
}
function introduce(greeting, ...names) {
    return `${greeting}, ${names.join(", ")}!`;
}

Destructuring parameters

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

function printUser({ name, age, city = "Seoul" }) {
    console.log(`${name} (${age}, ${city})`);
}
function getMinMax([first, ...rest]) {
    return {
        min: Math.min(first, ...rest),
        max: Math.max(first, ...rest)
    };
}

Returning multiple values

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

function getCoordinates() {
    return [10, 20];
}
const [x, y] = getCoordinates();
function getUserInfo() {
    return { name: "Alice", age: 25, city: "Seoul" };
}
const { name, age } = getUserInfo();

3. Higher-order functions

Functions as arguments

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다, 반복문으로 데이터를 처리합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

function repeat(n, action) {
    for (let i = 0; i < n; i++) {
        action(i);
    }
}
repeat(3, console.log);
repeat(3, i => console.log(`iteration ${i}`));

Functions that return functions

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

function makeMultiplier(factor) {
    return function(x) {
        return x * factor;
    };
}
const double = makeMultiplier(2);
const triple = makeMultiplier(3);
const makeMultiplier = factor => x => x * factor;

Array higher-order methods

아래 코드는 javascript를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(x => x * 2);
const evens = numbers.filter(x => x % 2 === 0);
const sum = numbers.reduce((acc, x) => acc + x, 0);
const result = numbers
    .filter(x => x % 2 === 0)
    .map(x => x * 2)
    .reduce((acc, x) => acc + x, 0);

4. Closures

What is a closure?

A closure is a function that remembers variables from the scope where it was created. 아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

function makeCounter() {
    let count = 0;
    return function() {
        count++;
        return count;
    };
}
const counter = makeCounter();
console.log(counter());  // 1
console.log(counter());  // 2
const counter2 = makeCounter();
console.log(counter2());  // 1

Private state

다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

function createBankAccount(initialBalance) {
    let balance = initialBalance;
    return {
        deposit(amount) {
            if (amount > 0) balance += amount;
            return balance;
        },
        withdraw(amount) {
            if (amount > 0 && amount <= balance) {
                balance -= amount;
                return balance;
            }
            return null;
        },
        getBalance() {
            return balance;
        }
    };
}

More examples

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

function makeAdder(x) {
    return y => x + y;
}
function memoize(fn) {
    const cache = {};
    return function(...args) {
        const key = JSON.stringify(args);
        if (key in cache) return cache[key];
        const result = fn(...args);
        cache[key] = result;
        return result;
    };
}

5. this binding

Ordinary functions

아래 코드는 javascript를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

const person = {
    name: "Alice",
    greet: function() {
        console.log(`Hello, ${this.name}.`);
    }
};
person.greet();
const greetFunc = person.greet;
// greetFunc();  // loses `this` in non-strict sloppy mode / undefined in strict

Arrow functions and this

아래 코드는 javascript를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

const person = {
    name: "Alice",
    hobbies: ["reading", "sports", "coding"],
    printHobbies2: function() {
        this.hobbies.forEach(hobby => {
            console.log(`${this.name}'s hobby: ${hobby}`);
        });
    }
};
person.printHobbies2();

bind, call, apply

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

const person = { name: "Alice" };
function greet(greeting, punctuation) {
    console.log(`${greeting}, ${this.name}${punctuation}`);
}
greet.call(person, "Hello", "!");
greet.apply(person, ["Hello", "."]);
const boundGreet = greet.bind(person);
boundGreet("Hi", "~");

6. Callbacks

Basics

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다, 반복문으로 데이터를 처리합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

function processArray(arr, callback) {
    const result = [];
    for (let item of arr) {
        result.push(callback(item));
    }
    return result;
}

Async callbacks

다음은 javascript를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

console.log("start");
setTimeout(() => {
    console.log("after 2s");
}, 2000);
console.log("end");
setTimeout(() => {
    console.log("1s");
    setTimeout(() => {
        console.log("2s");
        setTimeout(() => console.log("3s"), 1000);
    }, 1000);
}, 1000);

7. IIFE

아래 코드는 javascript를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

(function() {
    console.log("IIFE");
})();
(() => {
    console.log("arrow IIFE");
})();
const result = (function() {
    return 10 + 20;
})();

Module-style IIFE

아래 코드는 javascript를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

const counterModule = (function() {
    let count = 0;
    return {
        increment() { count++; return count; },
        decrement() { count--; return count; },
        getCount() { return count; }
    };
})();

8. Recursion

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

function factorial(n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}
function fibonacci(n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}
function sumArray(arr) {
    if (arr.length === 0) return 0;
    return arr[0] + sumArray(arr.slice(1));
}

9. Practical examples

Utilities: chunk, flatten, unique

다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

function chunk(arr, size) {
    const result = [];
    for (let i = 0; i < arr.length; i += size) {
        result.push(arr.slice(i, i + size));
    }
    return result;
}
function flatten(arr) {
    return arr.reduce((acc, item) =>
        acc.concat(Array.isArray(item) ? flatten(item) : item), []);
}
function unique(arr) {
    return [...new Set(arr)];
}

Composition

const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);

Debounce and throttle

다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

function debounce(func, delay) {
    let timeoutId;
    return function(...args) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => func(...args), delay);
    };
}
function throttle(func, delay) {
    let lastCall = 0;
    return function(...args) {
        const now = Date.now();
        if (now - lastCall >= delay) {
            lastCall = now;
            func(...args);
        }
    };
}

10. Common mistakes

Arrow functions as methods

아래 코드는 javascript를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

const person = {
    name: "Alice",
    greet: () => {
        console.log(this.name);  // wrong: lexical this
    }
};

Closures in loops with var

아래 코드는 javascript를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

for (var i = 0; i < 3; i++) {
    setTimeout(function() { console.log(i); }, 100);
}
for (let i = 0; i < 3; i++) {
    setTimeout(function() { console.log(i); }, 100);
}

11. Exercises

Currying

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다, 조건문으로 분기 처리를 수행합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

function curry(fn) {
    return function curried(...args) {
        if (args.length >= fn.length) return fn(...args);
        return (...nextArgs) => curried(...args, ...nextArgs);
    };
}

Pipeline

아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

function pipe(...fns) {
    return function(x) {
        return fns.reduce((acc, fn) => fn(acc), x);
    };
}

Summary

Key points

  1. Definitions: declarations hoist; expressions and arrows do not behave like declarations.
  2. Parameters: defaults, rest, destructuring.
  3. Higher-order: pass/return functions; map/filter/reduce.
  4. Closures: encapsulation and memoization.
  5. this: dynamic in ordinary methods; lexical in arrows—choose accordingly.

Best practices

  1. Prefer arrows for short callbacks when this should come from outside.
  2. Write small, pure functions when possible.
  3. Name functions clearly; limit parameter count.

Next steps


... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3