함수 표현식과 화살표 함수
Article
10강에서 함수를 만들고 불렀다. 이번 강의의 주제는 한 문장으로 요약된다.
자바스크립트에서 함수는 값이다.
숫자를 변수에 담듯 함수를 변수에 담을 수 있고, 숫자를 인자로 넘기듯 함수를 넘길 수 있다. 이 성질이 자바스크립트를 다른 언어와 다르게 만든다.
함수를 변수에 담는다
const greet = function () {
console.log("안녕하세요");
};
greet();
console.log(typeof greet);
- 안녕하세요
- 'function'
function 뒤에 이름이 없다. 이름 없는 함수를 만들어 greet이라는 변수에 넣었다. 이걸 함수 표현식이라 부른다. 10강에서 쓰던 방식은 함수 선언문이다.
메모리로 보면 이렇다. 3강에서 본 그림과 같다. 상자에 함수가 들어간 것뿐이다.
함수도 객체다. 상자에는 함수가 있는 위치가 적힌다
- count
- 10
- greet
- 0x4f2a
- function () { … }
선언문과 표현식의 차이
생김새 말고 실질적인 차이가 하나 있다.
sayHi();
sayHello();
function sayHi() {
console.log("선언문");
}
const sayHello = function () {
console.log("표현식");
};
- 선언문
- ReferenceError: Cannot access 'sayHello' before initialization
선언문은 정의보다 위에서 불러도 동작한다. 표현식은 안 된다.
함수 선언문
function name() {}
- 정의 위에서 호출해도 된다
- 이름이 필수
- 어디서든 부를 수 있어 편하다
- 그래서 순서가 뒤엉키기도 한다
함수 표현식
const name = function () {}
- 정의 아래에서만 호출할 수 있다
- 이름을 생략한다
const라 재할당이 막힌다- 읽는 순서와 실행 순서가 같다
화살표 함수
ES6에서 더 짧은 문법이 생겼다. function 키워드를 지우고 =>를 넣는다.
const add = function (a, b) {
return a + b;
};
const addArrow = (a, b) => {
return a + b;
};
console.log(add(1, 2), addArrow(1, 2));
- 3 3
여기서 더 줄일 수 있다. 규칙이 두 개 있다.
- 01
기본 형태
매개변수 괄호, 중괄호, return 이 모두 있다.
const double = (n) => { return n * 2; }; - 02
본문이 return 한 줄이면 중괄호와 return 을 지운다
남은 식의 결과가 자동으로 반환된다. 이걸 암묵적 반환이라 부른다.
const double = (n) => n * 2; - 03
매개변수가 하나면 괄호도 지운다
0개이거나 2개 이상이면 괄호가 필요하다.
const double = n => n * 2;
const double = n => n * 2;
const add = (a, b) => a + b;
const hello = () => "안녕";
console.log(double(5), add(1, 2), hello());
- 10 3 '안녕'
객체를 반환할 때 이 규칙이 걸림돌이 된다.
const makeUser = name => { name: name };
console.log(makeUser("지원"));
const makeUserOk = name => ({ name: name });
console.log(makeUserOk("지원"));
- undefined
- { name: '지원' }
첫 번째는 중괄호를 함수 본문으로 읽어버린다. 객체를 돌려주려면 괄호로 감싸 식이라고 알려줘야 한다.
함수를 인자로 넘긴다 — 콜백
함수가 값이라면, 함수를 다른 함수에 넘길 수도 있다. 넘겨받은 함수를 콜백이라 부른다.
function repeat(count, action) {
for (let i = 0; i < count; i++) {
action(i);
}
}
repeat(3, i => console.log(`${i}번째 실행`));
- 0번째 실행
- 1번째 실행
- 2번째 실행
repeat은 "몇 번 반복할지"만 알고, "무엇을 할지"는 모른다. 그건 넘겨받은 함수가 정한다. 반복 로직과 실제 작업이 분리된다.
- repeat 호출함수를 인자로 넘긴다
- repeat 내부언제 부를지 정한다
- action(i)넘긴 함수가 실행된다
이 패턴은 앞으로 계속 만난다. 16강의 map, filter도, 버튼 클릭 처리도, 20강의 비동기도 전부 콜백이다.
const numbers = [1, 2, 3];
numbers.forEach(n => console.log(n * 10));
- 10
- 20
- 30
화살표 함수가 다른 점
문법만 짧아진 게 아니다. this를 스스로 갖지 않는다.
| 항목 | 일반 함수 | 화살표 함수 |
|---|---|---|
| this | 호출 방식에 따라 정해진다 | 바깥에서 물려받는다 |
| arguments | 있다 | 없다 |
| new 로 호출 | 가능 | 불가능 |
| 문법 길이 | 길다 | 짧다 |
this가 무엇인지는 19강에서 다룬다. 지금 알아둘 것은 이것뿐이다. 화살표 함수는 일반 함수의 짧은 버전이 아니다. 동작이 다르다.
정리하면
- 함수는 값이다. 변수에 담고, 인자로 넘기고, 반환할 수 있다.
- 함수 선언문은 정의 위에서도 호출되지만, 표현식은 안 된다.
- 화살표 함수는 본문이 한 줄이면
return과 중괄호를 지운다. 객체를 반환하려면({ })로 감싼다. - 중괄호를 쓰면서
return을 빠뜨리면 **조용히undefined**가 나온다. - 다른 함수에 넘기는 함수를 콜백이라 부른다. 넘길 때 괄호를 붙이지 않는다.
- 화살표 함수는
this를 갖지 않는다. 짧은 버전이 아니라 다른 함수다.
다음 강의는 스코프다. 3강에서 var가 중괄호를 무시한다고 했던 그 이야기를 이제 제대로 푼다.