notes
26장. ES6 함수의 추가 기능
모던 JS Deep Dive — ES6 함수의 화살표 함수·매개변수·this 핵심 정리.
참고: 이웅모 《모던 자바스크립트 Deep Dive》 26장 · [MDN Arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) · [MDN Rest parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters)
ES6가 함수에 가져온 변화: 화살표, rest/spread, 기본 파라미터, 메서드 축약, 이름 추론. 문법이 짧아진 만큼 this·arguments·new·prototype 규칙이 갈라진다. 짧게 쓴 자리에 함정이 있다.
flowchart LR
AF[화살표] --> LEX[렉시컬 this]
AF --> NO[no arguments / new / prototype]
REST[rest] --> ARR[진짜 배열]
DEF[기본값] --> EVAL[필요 시 평가]
26.1 함수의 구분 (감각)
- 일반 함수(선언/표현식)
- 메서드(축약)
- 화살표
- 생성자/class
호출·정의 형태에 따라 this·[[Construct]]·prototype 유무가 다르다(17·18·22).
26.2 메서드
객체 리터럴 축약 method() {}는 사양상 method — non-constructor. new 불가.
obj.fn = function () {}는 일반 함수라 constructor.
const obj = {
m() {},
n: function () {},
};
// new obj.m(); // TypeError
new obj.n(); // OK (의도 없더라도)
26.3 화살표 함수
const add = (a, b) => a + b;
const id = x => x;
const block = (x) => { return x * 2; };
특징:
- 자기 this 없음 → 렉시컬 this(22)
- arguments 없음 → rest 사용
- new 불가, prototype 없음
- 가벼운 콜백에 강함 / 메서드·생성자에 약함
const counter = {
n: 0,
bad: () => { this.n += 1; }, // this가 counter 아님
good() { this.n += 1; },
};
26.4 rest 파라미터
function f(a, ...rest). rest는 진짜 Array. arguments 대체 1순위.
function sum(...nums) {
return nums.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3));
길이: f.length는 rest 앞 파라미터만 세는 편(18).
26.5 매개변수 기본값
function go(to = 'home', speed = 1) {
return { to, speed };
}
function f(a, b = a * 2) {
return [a, b];
}
기본값은 필요할 때 평가. undefined 전달 시 기본값 적용, null은 그대로 null.
26.6 무명/기명과 name
화살표·익명 표현식도 할당되면 name이 추론되는 경우가 많다(18). 디버깅에 유리.
예제
const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);
const trimLower = pipe((s) => s.trim(), (s) => s.toLowerCase());
console.log(trimLower(' Hi '));
function greet(name = 'guest', ...tags) {
return `${name}: ${tags.join(',')}`;
}
헷갈리던 장면 / 함정
- 화살표 메서드
- 화살표 + arguments 기대
- 기본값에 무거운 부작용
- rest 앞의 trailing comma 스타일만 보고 동작 오해
표
질문 → 자답
Q. 언제 function을 쓰나? A. this를 호출자가 정해야 하거나, arguments/new가 필요하거나, 메서드로 공유할 때.
Q. bind vs 화살표? A. bind는 새 함수+명시 this. 화살표는 정의 위치 this. 리스너 제거 시 참조 동일성 주의.
웹 보강 메모
MDN arrow의 “cannot be used as method” 경고를 팀에 공유. 린트 prefer-arrow-callback과 메서드 예외를 맞췄다.
실무로 바로
- 콜백: 화살표
- 객체 메서드: 축약
- 가변 인자: rest
- 옵션: 기본값 또는 옵션 객체
태그드 템플릿과의 거리
화살표·일반 함수 모두 태그드 템플릿의 태그로 쓸 수 있다. this 규칙만 지키면 된다.
const tag = (strings, ...vals) => strings[0] + vals.join('-');
console.log(tag`a${1}b${2}`);
IIFE와 화살표
(() => {
const secret = 1;
// ...
})();
모듈 이전 격리 패턴. 지금은 ESM이 우선(14).
요약 표 확장
질문 더
Q. rest와 arguments를 같이? A. 가능하지만 혼란. rest만.
Q. 기본값이 매 호출 새 객체?
A. = {} / = []는 호출마다 새로 만들어질 수 있다. 공유 뮤터블 기본값은 피한다.
파라미터 기본값과 TDZ
function f(a = b, b = 1) {
// a 기본값 평가 시 b는 TDZ일 수 있음
}
// f(); // ReferenceError in many engines
function g(a = 1, b = a) {
return [a, b];
}
console.log(g()); // [1, 1]
기본값 평가 스코프는 파라미터 칸. 앞에서 뒤로 참조는 OK, 반대는 TDZ.
화살표 본문이 객체를 반환할 때
const make = (id) => ({ id }); // 괄호 필수 — 블록과 구분
const bad = (id) => { id }; // undefined 반환
메서드 정의 비교 표
실전 리팩터
// before
function handle(a, b, c) {
a = a || 0;
b = b || '';
// …
}
// after
function handle(a = 0, b = '', ...rest) {
// …
}
falsy 함정(||)을 기본값이 줄여 준다. 0/''이 유효면 ?? 또는 기본값.
즉시 평가되는 기본값 실수
function bad(ts = Date.now()) {
return ts;
}
const a = bad();
const b = bad();
// 호출 시점마다 새 now — 의도면 OK, “고정 기본”이 아님
설정 객체는 호출 밖에서 만들거나 팩토리로.
화살표와 super
화살표는 super를 자기 방식으로 갖지 못한다. class 필드 화살표에서 super 호출 패턴은 제약이 있다. 프로토타입 메서드에서 super.
결론 체크리스트
- 콜백인가 메서드인가 → 화살표 vs 축약
- this가 필요한가 → 호출 규약 확인
- 가변 인자인가 → rest
- 옵션인가 → 기본값 또는 옵션 객체
- new가 필요한가 → 화살표/축약 메서드 제외
여기서 잠깐 💁♂️
27 배열 — 고차 메서드가 화살표와 함께 일상이 된다.
보강 — 중첩 기본값과 파괴
function createUser({ name = 'anon', role = 'member' } = {}) {
return { name, role };
}
console.log(createUser());
console.log(createUser({ name: '민섭' }));
인자 자체가 undefined일 때 = {}가 받아서 안쪽이 기본값으로 채워진다. API 옵션 객체 패턴의 정석에 가깝다.
보강 — 화살표와 스택
기명 function은 스택에 이름이 잘 남는다. 화살표는 name 추론·변수명에 의존. 핫 경로 디버깅이 어려우면 기명 표현식을 섞는다.