05. 함수 기초
함수 선언문은 호이스팅되어 위에서도 호출할 수 있습니다. 표현식과 화살표 함수는 변수에 할당된 이후부터 사용 가능합니다. 화살표 함수는 짧고 자체 `this` 를 가지지 않아 콜백에 적합합니다.
이 강의에서 배우는 것
- 1함수 선언문과 함수 표현식, 화살표 함수를 작성할 수 있다.
- 2매개변수의 기본값, 나머지 매개변수(rest) 를 사용할 수 있다.
- 3인자(argument) 와 매개변수(parameter) 의 차이를 설명할 수 있다.
- 4함수 스코프와 블록 스코프를 구분한다.
- 5순수 함수(pure function) 의 개념을 이해한다.
소개
함수 선언문은 호이스팅되어 위에서도 호출할 수 있습니다. 표현식과 화살표 함수는 변수에 할당된 이후부터 사용 가능합니다. 화살표 함수는 짧고 자체 `this` 를 가지지 않아 콜백에 적합합니다.
핵심 개념
1. 함수 선언 vs 표현식 vs 화살표
함수 선언문은 호이스팅되어 위에서도 호출할 수 있습니다. 표현식과 화살표 함수는 변수에 할당된 이후부터 사용 가능합니다. 화살표 함수는 짧고 자체 `this` 를 가지지 않아 콜백에 적합합니다.
function add(a, b) { return a + b; } // 선언문
const sub = function (a, b) { return a - b; }; // 표현식
const mul = (a, b) => a * b; // 화살표2. 매개변수와 인자
매개변수에 기본값을 지정할 수 있고, `...rest` 로 가변 인자를 받을 수 있습니다.
function greet(name = "친구") {
return `안녕, ${name}!`;
}
function sum(...nums) {
return nums.reduce((a, b) => a + b, 0);
}3. return 과 부수 효과
함수는 명시적으로 `return` 한 값을 돌려주며, 없으면 `undefined` 입니다. 입력이 같으면 항상 같은 결과를 반환하고 외부 상태를 바꾸지 않는 함수를 "순수 함수" 라 부릅니다.
// 순수
const square = (x) => x * x;
// 비순수: 외부 상태 변경
let counter = 0;
const tick = () => { counter += 1; };4. 스코프
변수는 선언된 블록 안에서만 보입니다. `let`/`const` 는 블록 스코프, `var` 는 함수 스코프입니다. 함수 안에서 바깥 변수를 참조하는 것을 클로저(다음 단계에서 자세히) 라고 합니다.
function outer() {
const a = 1;
if (true) {
const b = 2;
console.log(a, b); // 1 2
}
// console.log(b); // ReferenceError
}핵심 예제
| 파일 | 다루는 내용 |
|---|---|
| `01_declaration.js` | 함수 선언문과 호이스팅 |
| `02_expression.js` | 함수 표현식과 화살표 함수 |
| `03_params.js` | 기본값, 나머지 매개변수, 구조 분해 |
| `04_scope.js` | 블록/함수 스코프와 변수 접근 범위 |
src/01_declaration.js
/** 함수 선언문은 호이스팅되어 정의 이전에도 호출 가능하다. */
console.log("3 + 4 =", add(3, 4));
function add(a, b) {
return a + b;
}
/** 사각형의 넓이를 구한다. */
function area(w, h) {
return w * h;
}
console.log("area(5,6) =", area(5, 6));
src/02_expression.js
/** 함수 표현식과 화살표 함수를 비교한다. */
const sub = function (a, b) {
return a - b;
};
const mul = (a, b) => a * b;
// 한 줄 본문에서 객체를 반환할 땐 괄호로 감싼다
const wrap = (x) => ({ value: x });
console.log(sub(10, 3));
console.log(mul(4, 5));
console.log(wrap(42));
src/03_params.js
/** 기본값, 나머지 매개변수, 구조 분해를 함께 사용한다. */
function greet(name = "친구", greeting = "안녕") {
return `${greeting}, ${name}!`;
}
function sum(...nums) {
return nums.reduce((acc, n) => acc + n, 0);
}
function describe({ name, age = "?" } = {}) {
return `${name} (${age}세)`;
}
console.log(greet());
console.log(greet("Ada", "Hi"));
console.log(sum(1, 2, 3, 4, 5));
console.log(describe({ name: "Linus" }));
src/04_scope.js
/** 블록 스코프와 함수 스코프의 차이를 확인한다. */
function demo() {
const outer = "바깥";
if (true) {
const inner = "안쪽";
console.log(outer, inner);
}
// console.log(inner); // ReferenceError
}
demo();
// 클로저 맛보기: 함수가 자기가 선언된 환경의 변수를 기억한다
function makeCounter() {
let count = 0;
return () => (count += 1);
}
const next = makeCounter();
console.log(next(), next(), next()); // 1 2 3
자주 하는 실수
- 화살표 함수에서 `this` 가 외부의 `this` 라는 사실을 잊고 메서드로 정의해 버그를 만드는 경우.
- 매개변수 기본값이 `undefined` 일 때만 적용된다는 사실을 잊고 `null` 을 넘기는 경우.
- `return` 을 빠뜨려 `undefined` 가 반환되는 줄 모르는 경우.
- 화살표 함수에서 객체 리터럴을 바로 반환할 때 괄호를 빠뜨림 (`() => ({ a: 1 })`).
- 함수가 외부 변수를 몰래 변경해 추적이 어려운 버그를 만드는 경우.
FAQ
Q1. 선언문과 표현식 중 무엇을 쓸까요?
모듈 최상단에 정의되는 유틸은 선언문이 가독성이 좋고, 콜백/지역 함수는 화살표가 간결합니다.
Q2. 인자가 너무 많아질 땐?
객체로 묶어 받으세요. `function create({ name, age, role }) { ... }` 처럼 구조 분해를 활용합니다.
Q3. 함수도 값인가요?
네. 변수에 할당하고, 다른 함수에 인자로 넘기고, 결과로 반환할 수 있습니다. 이를 "일급 함수" 라고 부릅니다.
과제
- `homework_01.js` — 원의 반지름을 받아 넓이와 둘레를 반환하는 함수.
- `homework_02.js` — 가변 인자로 받은 숫자들의 평균을 구하는 함수 (빈 배열 처리 포함).
homework/README.md
## homework_01.js
- 반지름 `r` 을 받아 `{ area, perimeter }` 객체를 반환하는 함수를 작성하세요.
- `Math.PI` 를 사용하고, 소수점 둘째 자리까지 반올림하세요 (`Number(x.toFixed(2))`).
## homework_02.js
- 임의 개수의 숫자를 받아 평균을 구하는 함수 `average(...nums)` 를 작성하세요.
- 인자가 하나도 없으면 `0` 을 반환해야 합니다.
homework/answer/homework_01.js
/** 원의 넓이와 둘레를 반환한다. */
function circle(r) {
const area = Math.PI * r * r;
const perimeter = 2 * Math.PI * r;
return {
area: Number(area.toFixed(2)),
perimeter: Number(perimeter.toFixed(2)),
};
}
console.log(circle(1));
console.log(circle(5));
console.log(circle(10));
homework/answer/homework_02.js
/** 가변 인자로 받은 숫자들의 평균을 구한다. */
function average(...nums) {
if (nums.length === 0) return 0;
const total = nums.reduce((acc, n) => acc + n, 0);
return total / nums.length;
}
console.log(average()); // 0
console.log(average(10)); // 10
console.log(average(1, 2, 3, 4, 5)); // 3
console.log(average(90, 80, 70)); // 80
다음 단원
[06_배열과_문자열](../../02_데이터_다루기/06_배열과_문자열/) — 데이터를 모아서 다루는 방법을 배웁니다.