함수
1. 함수란?
input을 받아서 output을 내보내는 일련의 과정
함수는 함수 정의(Function definition)를 통해 생성한다.
JS의 함수는 다양한 방법으로 정의할 수 있다.
함수의 정의만으로 함수가 실행되지 않는다. 인수 -> 매개변수를 통해 함수에게 전달하면서 함수의 실행을 명시적으로 지시해야한다.
이를 함수호출(Function call/invoke)이라 한다.
1 | // f(x, y) = x + y |
함수를 호출하면 코드 블록에 담긴 문들이 일괄적으로 실행되고 반환값을 반환한다.
2. 함수의 사용 이유
- 동일한 작업을 반복적으로 수행한다면, 미리 정의된 함수를 재사용하는 것이 효율적이다.
함수는 얼마든지 호출할 수 있으므로 코드의 재사용의 측면에서 매우 유용하다. - 함수는 유지보수의 편의성을 높이고 실수를 줄여 코드의 신뢰성을 높이는 효과가 있다.
- 코드의 가독성을 향상시킨다. (객체타입의 값이라 식별자를 붙일 수 있음)
3. 함수 리터럴
JS의 함수는 객체 타입의 값
함수 리터럴은 function 키워드, 함수 이름, 매개변수, 함수 몸체로 구성된다.
1 | // 변수에 함수 리터럴을 할당 |
함수는 호출할 수 있지만, 일반 객체는 호출할 수 없다.
함수 객체만의 고유한 프로퍼티를 갖는다.
함수이름
- 함수 이름은 식별자. 네이밍 규칙을 준수해야한다.
- 함수 이름은 함수 몸체 내에서만 참조할 수 있는 식별자이다.
- 함수 이름은 생략 가능하다.
매개변수 목록
- 0개 이상의 매개변수를 소괄호로 감싸고 쉼표로 구분한다.
- 함수 호출문의 인수가 순서대로 할당된다. 매개변수 목록은 순서에 의미가 있다.
- 함수 몸체 내에서 변수와 동일하게 취급된다. 변수와 마찬가지로 식별자 네이밍 규칙을 준수해야한다.
함수 몸체
- 함수 몸체는 함수 호출에 의해 실행된다.
- 함수가 호출되었을 때 일괄적으로 실행될 문들을 하나의 실행 단위로 정의한 코드 블록이다.
4. 함수 정의
함수를 호출하기 이전에 인수를 전달받을 매개변수와 실행할 문들, 그리고 반환할 값을 지정하는 것을 말한다.
1 | // 함수 선언문 |
4.1 함수 선언문
- 함수 선언문은 리터럴과 형태가 동일하다. 함수 선언문은 함수 이름을 생략할 수 없다.
- 함수 선언문은 표현식이 아닌 문이다. (선언문이기 때문에 undefined를 출력한다.)
- 표현식이 아닌 문은 변수에 할당할 수 없지만, 함수 선언문은 변수에 할당하는 것 처럼 보인다.
- JS 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고 생성된 함수 객체를 할당한다.
- 함수는 함수 이름으로 호출하는게 아니라 함수 객체를 가리키는 식별자로 호출한다.
자바스크립트 엔진은 함수선언문을 함수 표현식으로 변환하여 함수 객체를 생성한다고 생각할 수 있다.
4.2 함수 표현식
자바스크립트의 함수는 일급 객체 (함수를 값처럼 자유롭게 사용할 수 있음)
일급 객체이므로 함수 리터럴로 생성한 함수 객체를 변수에 할당할 수 있다.
함수 리터럴의 함수 이름은 생략할 수 있다. (생략하는 것이 일반적, 익명 함수)
함수 선언문과 함수 표현식의 차이. 함수 생성 시점과 호이스팅
4.3 함수 생성 시점과 함수 호이스팅
함수 선언문과 함수 표현식은 함수 생성 시점이 다르다.
- 함수 선언문으로 함수를 정의하면 런타임 이전에 함수 객체가 먼저 생성된다.
자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고 함수 객체를 할당 - 함수 선언문을 통해 암묵적으로 생성된 식별자는 함수 객체로 초기화
함수 표현식은 변수 할당문의 값이 함수 리터럴인 문
- 함수 표현식은 변수 선언문과 변수 할당문을 한번에 기술한 축약 표현과 동일하게 동작한다.
- 변수 할당문의 런타임에 평가되므로 함수 표현식의 함수 리터럴도 할당문이 실행되는 시점에 평가되어 함수 객체가 된다.
- 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생한다.
- 함수 표현식 이전에 함수를 참조하면 타입에러가 발생한다.
- 함수 표현식으로 정의한 함수는 반드시 함수 표현식 이후에 참조 또는 호출해야 한다.
4.4 Function 생성자 함수 (빌트인 함수) (Constructor Function)
- 생성자 함수는 객체를 생성하는 함수.
- Function 생성자 함수로 생성한 함수는 클로저를 생성하지 않는 등, 함수 선언문이나 함수 표현식으로 생성한 함수와 다르게 동작한다.
4.5 화살표 함수
- 화살표 함수는 항상 익명 함수로 정의한다.
- 생성자 함수로 사용할 수 없으며 기존의 함수와 this 바인딩 방식이 다르고, prototype 프로퍼티가 없으며 arguments 객체를 생성하지 않는다.
5. 함수 호출
- 함수는 함수를 가리키는 식별자와 한 쌍의 소괄호인 함수 호출 연산자로 호출한다.
- 함수 호출 연산자 내에는 0개 이상의 인수(argument)를 쉼표로 구분하여 나열한다.
- 호출하면 현재의 실행 흐름을 중단, 호출된 함수로 컨트롤을 넘긴다.
인수 -> 매개변수 할당 , 함수 몸체의 문들이 실행
5.1 매개변수와 인수
함수 외부에서 함수 내부로 필요 값을 전달할 필요가 있는 경우 인수(외부) -> 매개변수(내부)
- 인수는 값으로 평가될 수 있는 표현식이어야 하며, 함수를 호출할 때 지정하며 개수와 타입에 제한이 없다.
- 매개변수는 함수를 정의할 때 선언하며 함수 몸체 내부에서 변수와 동일하게 취급한다.
(함수가 호출되면 함수 몸체 내에 암묵적으로 매개변수가 생성되고, undefined로 초기화된 이후 인수가 순서대로 할당된다.) 호출될 때마다 이 단계를 거침 - 매개변수는 함수 몸체 내부에서만 참조할 수 있고 함수 몸체 외부에서는 참조할 수 없다.
(스코프는 함수 내부이다.) - 매개변수와 인수의 개수를 체크하지 않는다.
- 인수가 부족하면 할당되지 않은 매개변수의 값은 undefined
- 초과된 인수는 무시된다. 모든 인수는 암묵적으로 arguments 객체의 프로퍼티로 보관된다.
5.2 인수 확인
- 자바스크립트 함수는 매개변수와 인수의 개수가 일치하는지 확인하지 않는다.
- 자바스크립트 함수는 매개변수의 타입을 사전에 지정할 수 없다.
따라서 함수를 정의할 때 적절한 인수가 전달되었는지 확인이 필요하다.
5.3 매개변수의 최대 개수
- 이상적인 매개변수 개수는 0개이며 적을 수록 좋다.
- 3개 이상을 넘지 않는 것을 권장한다. (그 이상의 매개변수가 필요하다면 하나의 매개변수를 선언하고 객체를 인수로 전달받는 것이 유리하다.)
- 매개변수의 개수나 순서가 변경되면 함수의 호출 방법도 변경되므로 함수를 사용하는 코드 전체가 영향을 받는다. (유지보수성도 나빠진다.)
5.4 반환문
- 실행 결과를 함수 외부로 반환(return)
- 반환문은 함수의 실행을 중단하고 함수 몸체를 빠져나간다.
- 반환문 이후에 다른 문이 존재하면 그 문은 무시된다.
- return 키워드 뒤에 지정한 값을 반환한다. 명시적을 지정하지 않으면 undefined가 반환된다.
- 반환문을 생략할 수 있다. 함수는 마지막 문까지 실행한 후 암묵적으로 undefined를 반환한다.
6. 참조에 의한 전달과 외부 상태의 변경
함수의 매개변수에 값을 전달하는 방식 Call by value, Call by reference
동작 방식은 값에 의한 전달, 참조에 의한 전달
1 | //primitive은 원시값, obj는 객체를 전달받는다. |
원시 값은 원본이 훼손되지 않는다. 객체는 원본이 훼손된다.
- 원시 타입 인수는 값 자체가 복사되어 매개변수에 전달되기 때문에 원본은 훼손되지 않는다. side-effect가 없다
- 객체 타입 인수는 참조값이 복사되어 매개변수에 전달되기 때문에 원본이 훼손된다. side-effect 발생
- 객체를 불변 객체로 만들어 사용해서 외부상태가 변경되는 side-effect를 없앨 수 있다.
7. 다양한 함수의 형태
7.1 즉시실행함수(IIFE)
- 즉시 실행 함수는 단 한번만 호출되며 다시 호출할 수 없다. (첫번째 메인 페이지에 사용)
- 익명 함수를 사용하는 것이 일반적이다.
1
2
3
4
5(function () {
var a = 3;
var b = 5;
return a + b;
}()); - 즉시 실행 함수는 반드시 그룹 연산자()로 감싸 주어야 한다.
- 그룹 연산자로 함수를 묶은 이유는 먼저 함수를 평가하여 함수 객체를 생성하기 위함이다.
7.2 재귀 함수(recursive function)
- 함수가 자기 자신을 호출하는 것을 재귀 호출이라 한다.
- 팩토리얼은 재귀 호출로 간단히 구현할 수 있다.
- 재귀 호출을 멈출 수 있는 탈출 조건을 반드시 만들어야 한다.
- 함수 호출은 반드시 함수를 가리키는 식별자로 해야 한다.
- 재귀 함수는 for 문이나 while 문으로 구현 가능하다.
7.3 중첩 함수(nested function)
- 함수 내부에 정의된 함수를 중첩함수 또는 내부 함수(inner function)라 한다.
- 중첩 함수를 포함하는 함수를 외부 함수(outer function)라 한다.
- 일반적으로 중첩 함수는 자신을 포함하는 외부 함수를 돕는 헬퍼 함수 역할을 한다.
7.4 콜백 함수(Callback function)
고차함수(Higher-Order Function, HOF)의 인자로 넘겨지는 함수.
콜백 함수는 고차함수 내에서 수행된다. (내용 추가하기)
7.5 순수 함수와 비순수 함수
순수 함수 - 부수효과가 없는 함수(외부 상태를 변경시키는)
비순수 함수 - 부수효과가 있는 함수
함수형 프로그래밍은 순수 함수를 통해 부수 효과를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높이려는 노력의 한 방법이라고 할 수 있다.