티스토리 뷰
12.2 함수를 사용하는 이유
동일한 작업을 반복적으로 수행할 때 미리 정의된 함수를 재사용하는 것이 효율적
유지보수 편의성
코드의 신뢰성(실수 ↓)
코드의 가독성(적절한 이름을 가졌다면 함수의 역할을 파악하는데 도움됨)
코드는 개발자를 위한 문서 -> 가독성 좋은 코드 = 좋은 코드
12.3 함수 리터럴
자바스크립트의 함수는 객체(다른 언어와 차이. > 18. 함수와 일급 객체에서 계속)
일반 객체와 달리 호출 가능하고 고유한 프로퍼티를 가짐
함수 이름은 함수 몸체 내에서만 참조할 수 있는 식별자
12.4 함수 정의
변수는 선언 함수는 정의라고 표현
함수 선언문이 평가되면 식별자가 암묵적으로 생성되고 함수 객체가 할당됨
1 함수 선언문
function add(x, y) {
return x + y;
}
- 표현식이 아닌 문
자바스크립트 엔진이 코드 문맥에 따라 동일한 함수 리터럴을
함수 선언문(표현식이 아닌 문)으로 해석하거나,
함수 리터럴 표현식(표현식인 문)으로 해석함
{ }
단독으로 존재하면 블록문으로 해석,
값으로 평가되어야할 문맥(ex. 할당 연산자의 우변)에서 피연산자로 사용되면 객체 리터럴으로 해석
기명 함수 리터럴
단독으로 사용하면 함수 선언문으로 해석,
값으로 평가되어야하는 문맥(ex. 변수에 할당, 피연산자로 사용)에서는 함수 리터럴 표현식으로 해석
-> 함수를 생성하는 내부 동작에 차이가 있음
- 함수 이름을 생략할 수 없음
자바스크립트 엔진은 함수 호출을 위해 함수 이름과 동일한 식별자를 암묵적으로 생성하고 거기에 함수 객체를 할당
=> 함수 이름으로 호출하는 것이 아닌 식별자로 호출
// 함수 선언문 정의 시 자바스크립트 엔진의 동작을 표현한 의사 코드
const add = function add(x, y) {
return x + y;
}
- 함수 호이스팅
호이스팅
: 선언문이 코드(스코프)의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징
모든 선언문은 런타임 이전에 자바스크립트 엔진에 의해 먼저 실행됨(= 소스코드 평가 과정)
함수 선언문을 통해 암묵적으로 생성된 식별자는 함수 객체로 초기화 그 외 키워드는 undefined로 초기화
=> 함수 선언문은 선언 전 호출 가능, 함수 표현식은 TypeError 발생
함수 선언문의 함수 호이스팅은 함수를 호출하기 전 반드시 함수를 선언해야 한다는 규칙을 무시하기 때문에
함수 표현식 사용을 권장하기도 함(Douglas Crockford - 자바스크립트 핵심 가이드 저자, JSON 창안)
2 함수 표현식
const add = function (x, y) {
return x + y;
}
- 표현식인 문
- 익명 함수: 함수 이름 생략 가능
- 변수 호이스팅
3 Function 생성자 함수
const add = new Function('x', 'y', 'return x + y');
매개변수 목록과 함수 본문을 문자열로 전달
- 클로저를 생성하지 않음(클로저 함수에서 정의한 변수에 접근하는 경우 ReferenceError 발생)
4 화살표 함수
const add = (x, y) => x + y;
기존 함수와 비교하여 내부 동작이 간략
- 생성자 함수로 사용할 수 없음
- 기존 함수와 this 바인딩 방식이 다름
- prototype 프로퍼티 없음
- arguments 객체 생성하지 않음
(... 26.3 화살표 함수에서 계속)
12.5 함수 호출
함수를 호출하면 현재의 실행 흐름을 중단하고 호출된 함수로 실행 흐름을 옮김
-> 매개변수에 인수가 순서대로 할당되고 함수 본문의 문들이 실행
12.5.1 매개변수와 인수
인수가 매개변수의 수보다 부족하면 undefined로 인식, 초과하면 무시됨
초과된 인수 포함 모든 인수는 암묵적으로 arguments 객체의 프로퍼티로 보관됨
arguments 객체: 매개변수 개수를 확정할 수 없는 가변 인자 함수를 구현할 때 유용하게 사용됨(18.2.1 arguments 프로퍼티에서 계속)
12.5.2 인수 확인
1. 자바스크립트 함수는 매개변수와 인수의 개수가 일치하는지 확인하지 않음
2. 자바스크립트는 동적 타입 언어이기 때문에 자바스크립트 함수는 매개변수 타입을 사전에 지정할 수 없음
- 적절한 인수가 전달되었는지 확인
이 경우 잘못된 인수가 전달되었더라도 런타임에 에러가 발생(-> 타입스크립트 사용: 컴파일 시점에 알 수 있음)
- arguments 객체를 통해 인수 개수를 확인 / 단축 평가나 매개변수 기본값을 사용하여 기본값 지정
12.5.3 매개변수의 최대 개수
함수 호출 시 매개변수의 순서를 고려해야함
매개변수 개수나 순서가 변경되면 함수를 사용하는 코드 전체가 영향 받음(> 유지보수에 안좋음)
=> 매개변수 개수는 적을수록 좋음(2개 이하 권장, 객체 전달 고려)
12.6 참조에 의한 전달과 외부 상태의 변경
인수로 객체를 받을 경우 함수 내부에서 객체를 변경함으로써 부수 효과가 일어나지 않도록 주의
-> 함수가 외부 상태(외부값)를 변경하면 상태 변화를 추적하기 어려워짐
깊은 복사 사용하기
순수 함수를 통해 부수 효과를 억제하는 함수형 프로그래밍 적용하기
12.7 다양한 함수의 형태
12.7.1 즉시 실행 함수
정의와 동시에 즉시 호출되는 함수
- 다시 호출할 수 없음
- 익명 함수가 일반적(그룹 연산자 내부 기명 함수는 함수 리터럴로 평가되기 때문. 12.4 함수 정의 참고)
- 함수 리터럴로 평가하여 함수 객체를 생성하기 위해 그룹 연산자 사용(그룹 연산자의 피연산자는 값으로 평가됨)
함수 리터럴로 평가하여 함수 객체를 생성할 다른 방법을 사용해도 무방
(function () { ... }());
(function () { ... })();
!function () { ... }();
+function () { ... }();
- 그룹 연산자 사용 시 주의
자바스크립트 엔진은 함수 코드 블록 닫는 중괄호 뒤에 ';'를 암묵적으로 추가하기 때문에
피연산자가 없는 그룹 연산자로 인식하여 에러 발생
function foo() {}();
// function foo() {};(); // SyntaxError
12.7.2 재귀 함수
자기 자신을 호출하는 함수. 반복되는 처리를 위해 사용
재귀 함수에서 함수 이름/식별자로 자기 자신을 호출할 수 있음 (함수 이름은 함수 몸체에서만 유효)
const factorial = function foo(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
const factorial = function foo(n) {
if (n <= 1) return 1;
return n * foo(n - 1);
}
재귀 함수는 자신을 무한 재귀 호출하기 때문에 재귀 호출을 멈출 수 있는 탈출 조건을 반드시 만들어야 함
-> 탈출 조건이 없다면 함수가 무한 호출되어 스택 오버플로 에러가 발생
반복문을 사용하는 것보다 재귀 함수를 사용하는 것이 직관적으로 이해하기 쉬울 때만 한정적으로 사용하는 것이 바람직
12.7.3 중첩 함수(내부 함수)
함수 내부에 정의된 함수
일반적으로 외부 함수를 돕는 헬퍼 함수 역할
외부 함수: 중첩 함수를 포함하는 함수
스코프와 클로저와 관련
12.7.4 콜백 함수
함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수
고차함수: 매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수(27.9 배열 고차 함수)
함수의 공통 로직은 미리 정의해두고
변경되는 로직만 추상화하여 함수 내부로 전달
헬퍼 함수 역할
12.7.5 순수 함수와 비순수 함수
순수 함수
외부 상태에 의존하지 않고 오직 매개변수를 통해 값을 계산해 반환
일반적으로 하나 이상의 인수를 가짐(인수가 없는 순수 함수는 상수와 마찬가지)
인수를 변경하지 않음
외부 상태를 변경하지 않음
비순수 함수
외부 상태(전역 변수, 서버 데이터, 파일, console, dom)에 따라 반환값이 달라지는 함수
부수 효과가 있음
외부 상태에 의존하거나 외부 상태를 변경하는 함수
함수형 프로그래밍: 순수 함수와 보조 함수의 조합을 통해 외부 상태를 변경하는 부수 효과를 최소화해서 불변성을 지향하는 프로그래밍 패러다임
'책' 카테고리의 다른 글
[딥다이브] 14. 전역 변수의 문제점 (0) | 2024.04.28 |
---|---|
[딥다이브] 13. 스코프 (0) | 2024.04.22 |
[딥다이브] 11. 원시 값과 객체의 비교 (1) | 2023.12.23 |
[딥다이브] 10. 객체 리터럴 (2) | 2023.12.03 |
[딥다이브] 9. 타입 변환과 단축 평가 (2) | 2023.12.03 |