자바스크립트 기초 #4 함수

#3 제어 흐름 에서 분기와 반복을 봤으니, 이번엔 재사용 가능한 코드 단위를 만드는 도구 — 자바스크립트의 함수를 다룹니다.

함수 선언 (Function Declaration) #

가장 전통적인 형태.

함수 선언
function add(a, b) {
  return a + b;
}

add(2, 3);   // 5

키워드 function으로 시작하고 이름을 가집니다. 가장 큰 특징은 호이스팅(잠시 뒤 설명) 이라 코드 어디서 호출해도 동작한다는 점입니다.

함수 표현식 (Function Expression) #

함수를 값으로 다루는 형태.

함수 표현식
const add = function(a, b) {
  return a + b;
};

add(2, 3);   // 5

function 키워드가 식의 오른쪽에 있습니다. 변수 add에 함수가 들어간 거고, 변수와 같은 규칙으로 동작합니다(블록 스코프, 호이스팅 안 됨).

화살표 함수 (Arrow Function) #

ES2015에 추가된 짧은 형태. 콜백처럼 짧은 함수에 매우 자주 씁니다.

화살표 함수
const add = (a, b) => a + b;
const square = (n) => n * n;
const greet = (name) => {
  console.log(`안녕, ${name}!`);
};

add(2, 3);   // 5
square(5);   // 25
greet('커티스');

문법 요약:

  • 본문이 표현식 하나면 { return ... } 생략 가능
  • 매개변수가 하나면 괄호 생략 가능 (n => n * 2)
  • 매개변수가 0개거나 둘 이상이면 괄호 필수

화살표 함수와 일반 함수의 차이 — this #

가장 큰 차이는 this의 동작입니다. 일반 함수는 호출 방식에 따라 this가 달라지지만, 화살표 함수는 선언된 위치의 this를 그대로 가져갑니다.

this 차이 — 콜백에서의 의미
const obj = {
  name: '커티스',
  greetLater() {
    setTimeout(function() {
      console.log(this.name);    // undefined (this가 obj가 아님)
    }, 100);
  },
  greetLaterArrow() {
    setTimeout(() => {
      console.log(this.name);    // '커티스' (바깥 this 유지)
    }, 100);
  },
};

이 차이 때문에 콜백 함수는 화살표 함수, 객체 메서드는 일반 함수 또는 메서드 단축 문법이 흔한 컨벤션입니다. this고급 시리즈에서 깊이 다룹니다.

어떤 걸 언제 쓰나요? #

실무에서 가장 흔한 가이드:

  • 함수 선언 — 모듈 최상위에 두는 의미 있는 함수 (function calculate(...))
  • 화살표 함수 — 짧은 콜백, 변환, 계산 (map((x) => x * 2))
  • 함수 표현식 — 화살표가 없던 시절의 흔적. 새 코드에서는 거의 안 씀

이 시리즈도 그 가이드를 따릅니다.

매개변수 — 기본값 #

매개변수에 기본값을 줄 수 있습니다.

기본값 매개변수
function greet(name = '익명') {
  console.log(`안녕, ${name}!`);
}

greet();           // 안녕, 익명!
greet('커티스');    // 안녕, 커티스!
greet(undefined);  // 안녕, 익명!  ← undefined도 기본값 발동
greet(null);       // 안녕, null!  ← null은 그대로

undefined는 기본값을 발동시키지만 null은 그대로 전달됩니다. “값이 정해지지 않음"의 두 가지 의미(#2)가 여기서 다른 동작을 만듭니다.

매개변수 — 가변 인자 (...rest) #

인자를 몇 개 받을지 모를 때 ...으로 모을 수 있습니다.

rest 매개변수
function sum(...numbers) {
  return numbers.reduce((acc, n) => acc + n, 0);
}

sum(1, 2);              // 3
sum(1, 2, 3, 4, 5);     // 15
sum();                   // 0

...numbers나머지 인자들을 배열로 모읍니다. 마지막 매개변수에만 쓸 수 있습니다.

일반 인자와 함께 #

앞은 명시, 뒤는 rest
function logCall(label, ...args) {
  console.log(`[${label}]`, ...args);
}

logCall('debug', 1, 2, 3);
// [debug] 1 2 3

호출하는 쪽의 ...args펼치기(spread) 라고 부릅니다. 같은 ... 문법이지만 위치에 따라 의미가 달라요. 이 둘은 #5 객체와 배열 에서 다시 다룹니다.

반환 — return #

함수가 값을 돌려주는 키워드.

return
function double(n) {
  return n * 2;
}

double(5);   // 10

return을 만나면 함수가 즉시 종료됩니다. 그 뒤의 코드는 실행되지 않습니다.

이른 반환 (early return)
function describe(n) {
  if (n === 0) return '영';
  if (n < 0) return '음수';
  return '양수';
}

이른 반환은 들여쓰기를 줄이고 흐름을 직선화합니다. 깊은 if/else보다 거의 항상 읽기 좋습니다. 추천하는 패턴입니다.

return이 없으면 undefined #

return 없는 함수
function silent() {
  console.log('했음');
  // return 없음
}

const result = silent();
console.log(result);   // undefined

자바스크립트의 모든 함수는 무언가를 반환합니다. 명시적 return이 없으면 undefined가 자동으로 돌아옵니다.

호이스팅 — 함수 선언의 특수성 #

자바스크립트가 코드를 실행하기 전에, 함수 선언과 변수 선언을 미리 위로 끌어올리는 동작을 호이스팅(hoisting)이라 부릅니다.

함수 선언은 호이스팅이 완전히 일어나서, 코드 어디서든 호출할 수 있습니다.

호이스팅 — 함수 선언
console.log(add(2, 3));   // 5 — 선언 위에서 호출했는데 동작

function add(a, b) {
  return a + b;
}

반면 함수 표현식이나 화살표 함수는 변수라서, 선언 줄 이전에 쓰면 에러가 납니다.

호이스팅 — 표현식/화살표
console.log(add(2, 3));   // ✗ ReferenceError

const add = (a, b) => a + b;

대부분의 코드는 사용 전에 선언하기 때문에 호이스팅을 의식할 일은 적습니다. 다만 함수 선언만 끌어올려진다는 사실은 옛 코드를 읽을 때 종종 만나요.

클로저 — 함수가 자기 환경을 들고 다님 #

함수의 강력한 특성 한 가지를 미리 봅시다.

클로저 — 카운터 만들기
function createCounter() {
  let count = 0;

  return function() {
    count = count + 1;
    return count;
  };
}

const counter = createCounter();
counter();   // 1
counter();   // 2
counter();   // 3

createCounter가 끝났는데도 그 안의 count살아 있고 함수에 의해 기억됩니다. 이렇게 함수가 자기가 만들어진 환경(스코프)을 끌고 다니는 동작을 클로저라 부릅니다.

클로저는 자바스크립트의 가장 중요한 개념 중 하나로, 콜백,이벤트 핸들러,hook의 동작 모두에 들어 있습니다. 고급 시리즈에서 본격적으로 다룹니다. 지금은 “함수가 자기 변수를 기억한다” 만 잡아 두세요.

즉시 실행 함수 (IIFE) — 옛 패턴 #

옛 코드에서 자주 보이는 모양 한 가지.

IIFE — Immediately Invoked Function Expression
(function() {
  console.log('만들자마자 실행');
})();

함수를 정의하자마자 호출하는 패턴입니다. 옛날에는 모듈이 없어서 변수 스코프를 격리하기 위한 트릭으로 썼습니다. 모듈이 있는 지금은 거의 쓰지 않습니다. 옛 자료를 읽다가 만나면 “옛날 모듈 흉내” 정도로 알면 됩니다.

마무리 #

이번 글에서 정리한 내용:

  • 함수 정의 세 가지 — 선언 / 표현식 / 화살표
  • 화살표 함수의 가장 큰 차이는 this가 바깥에서 들어옴
  • 의미 있는 함수는 선언, 짧은 콜백은 화살표
  • 기본값 매개변수 — undefined 면 발동, null은 그대로
  • ...rest로 가변 인자 모으기
  • 이른 반환(early return) 으로 흐름 직선화
  • 함수 선언만 호이스팅 — 표현식은 변수 규칙
  • 클로저: 함수가 자기 환경을 기억

다음 글(#5 객체와 배열)에서는 자바스크립트의 두 핵심 자료구조 — 객체와 배열의 기본 사용법, 그리고 spread/디스트럭처링 같은 모던 문법을 다룹니다.

X