함수는 여러 줄의 작업에 이름을 붙여 두고 필요할 때마다 불러 쓰는 장치입니다. 이 글은 중복된 코드에서 출발해 함수로 묶고 매개변수를 붙이고 화살표 함수로 줄여 갑니다. 마지막에는 스코프와 호이스팅, 콜백을 봅니다.
1단계: 중복을 함수로 묶습니다
강좌 목록에 붙일 안내 문구를 만든다고 해 봅시다. 처음에는 이렇게 씁니다.
console.log("[HTML 강좌] 총 12편, 예상 40분");
console.log("[CSS 강좌] 총 9편, 예상 30분");
형식이 바뀌면 모든 줄을 고쳐야 합니다. 반복되는 모양을 함수로 묶으면 고칠 곳이 하나로 줄어듭니다.
function printNote() {
console.log("[HTML 강좌] 총 12편, 예상 40분");
}
printNote(); // 괄호를 붙여야 실행됩니다
function 이름() { } 형태를 함수 선언식이라고 합니다. printNote()처럼 괄호를 붙이는 순간 실행되고, 괄호 없이 printNote만 쓰면 함수 자체를 가리킬 뿐입니다.
2단계: 매개변수·반환값·기본값을 붙입니다
지금 함수는 같은 문장만 찍습니다. 바뀌는 부분을 괄호 안 이름으로 받으면 하나의 함수로 모든 강좌를 처리할 수 있습니다.
function makeNoteLabel(courseName, postCount, minutes) {
return `[${courseName} 강좌] 총 ${postCount}편, 예상 ${minutes}분`;
}
const label = makeNoteLabel("CSS", 9, 30);
console.log(label); // [CSS 강좌] 총 9편, 예상 30분
괄호 안의 courseName처럼 값을 받는 이름을 매개변수, 넣은 값 "CSS"를 인수라고 합니다. 흔한 실수가 return 대신 console.log만 쓰는 것입니다. 화면에는 값이 보이지만 함수의 결과는 undefined여서 const label에 담기지 않습니다.
인수를 빠뜨리면 그 매개변수는 undefined가 되어 문장이 깨집니다. 매개변수 뒤에 =로 기본값을 정해 두면 막을 수 있습니다.
function makeNoteLabel(courseName, postCount = 0, minutes = 5) {
return `[${courseName} 강좌] 총 ${postCount}편, 예상 ${minutes}분`;
}
console.log(makeNoteLabel("자바스크립트"));
// [자바스크립트 강좌] 총 0편, 예상 5분
기본값은 인수를 넘기지 않았을 때만 적용됩니다. 0이나 빈 문자열을 넘기면 그 값이 그대로 쓰입니다.
3단계: 함수 표현식과 화살표 함수
함수는 숫자나 문자열처럼 변수에 담을 수 있는 값입니다. 변수에 담는 형태를 함수 표현식, 이를 짧게 줄인 문법을 화살표 함수라고 합니다.
// 함수 표현식
const getReadTime = function (postCount) {
return postCount * 4;
};
// 화살표 함수 — function 키워드를 화살표로 대신합니다
const getReadTime2 = (postCount) => {
return postCount * 4;
};
// 한 줄이면 중괄호와 return을 생략합니다
const getReadTime3 = postCount => postCount * 4;
세 함수는 결과가 같습니다. 다만 화살표 함수에는 함정이 하나 있습니다. 화살표 함수는 자기만의 this를 갖지 않습니다. 객체의 메서드를 화살표 함수로 만들면 this가 그 객체를 가리키지 않아 값을 찾지 못합니다.
const note = {
title: "함수 정리",
showA: function () { console.log(this.title); },
showB: () => { console.log(this.title); }
};
note.showA(); // 함수 정리
note.showB(); // undefined
객체 안의 메서드는 일반 함수로, 짧은 계산이나 콜백은 화살표 함수로 쓰는 것이 무난한 기준입니다.
4단계: 스코프와 호이스팅
스코프는 변수 이름이 통하는 범위입니다. 함수 안에서 만든 변수는 그 함수 밖에서는 존재하지 않습니다.
const siteName = "카드뉴스노트"; // 전역 변수
function showTitle() {
const noteTitle = "스코프 정리"; // 지역 변수
console.log(siteName + " - " + noteTitle); // 둘 다 접근 가능
}
// console.log(noteTitle); // 오류: 함수 밖에서는 알 수 없습니다
전역 변수를 남발하면 이름이 충돌하기 쉬우므로 값은 되도록 함수 안에 가둬 둡니다. 한편 호이스팅은 선언이 위로 끌어올려진 것처럼 동작하는 현상입니다.
hello(); // 정상 — 선언식은 미리 등록됩니다
function hello() { console.log("안녕하세요"); }
bye(); // 오류: 아직 값이 담기기 전입니다
const bye = () => console.log("안녕히 가세요");
함수 선언식은 실행 전에 통째로 등록되지만, 변수에 담는 함수는 그 줄에 도달해야 값이 생깁니다. 그래서 const로 만든 함수는 정의한 뒤에 호출해야 합니다. 선언 방식이 헷갈린다면 자바스크립트 변수 편을 함께 보십시오.
5단계: 함수를 값으로 넘기는 콜백
함수를 다른 함수의 인수로 넘겨, 특정 시점에 대신 실행되게 하는 것을 콜백이라고 합니다.
function eachCourse(list, action) {
for (let i = 0; i < list.length; i++) {
action(list[i], i + 1);
}
}
const courses = ["HTML", "CSS", "자바스크립트"];
eachCourse(courses, (name, order) => {
console.log(`${order}번째 강좌: ${name}`);
});
eachCourse는 목록을 도는 일만 하고, 각 항목으로 무엇을 할지는 넘겨받은 함수가 정합니다. 버튼 클릭 처리도 같은 구조여서, 자바스크립트 이벤트 편에서 본격적으로 쓰입니다.
핵심 정리
- 선언식과 표현식 —
function 이름()은 미리 등록되고, 변수에 담은 함수는 정의한 줄 이후에만 쓸 수 있습니다. - 매개변수와 반환값 — 바뀌는 값은 매개변수로 받고 결과는
return으로 돌려줍니다. - 기본값 —
매개변수 = 값으로 인수를 빠뜨렸을 때를 대비합니다. - 화살표 함수 — 짧지만 자기
this가 없어 객체 메서드로는 부적합합니다. - 스코프와 콜백 — 변수는 함수 안에 가두고, 함수 자체를 값으로 넘겨 동작을 위임합니다.