함수 개념
프로그래밍에서 함수는 일련의 과정을 "문(Statement)"로 구현하고 코드블록으로 감싸서 하나의 실행 단위로 정의한 것이다. 쉽게 말하면 길고 더러운 코드를 한 단어로 축약한 것이다.
// 함수 정의
function sum(x, y) {
return x + y;
}
// 함수 호출
sum(2, 5); // 7
자바스크립트의 함수는 객체 타입의 값이며 여러 개 존재할 수 있고, 함수 또한 함수 리터럴로 생성할 수 있다. 입력값인 "인수(argument)"를 함수에 전달하여 함수를 호출하고, 호출된 함수는 코드블록의 문들을 일괄적으로 실행한 후 "반환값(return value)"을 반환한다.
함수의 구성요소는 다음과 같다.
- function 키워드
- 함수 이름: 함수 이름은 식별자이며, 함수 몸체 내부에서만 참조 가능하다.
- 매개변수 목록: 매개변수(parameter)란 함수 내부로 입력을 전달받는 변수를 말하며, 매개변수 목록은 순서에 의미가 있다.
- 함수 몸체: 함수 호출 시 일괄적으로 실행될 문들을 하나의 실행 단위로 정의한 코드블록이다.
함수를 사용하는 이유는 코드의 중복을 억제하고 재사용성을 높이고(유지보수의 편의성), 실수를 줄이기 위하여(코드의 신뢰성) 사용한다. 또한 적절한 함수 이름을 통해 쉽게 함수 역할을 파악할 수 있도록 할 수 있다.(코드의 가독성)
함수 정의하기
함수 정의는 함수를 호출하기 전, 인수를 전달받은 매개변수와 실행할 문들과 반환할 값을 지정하는 것을 말한다. 함수를 정의하는 방법에는 4가지가 있다. 방식이 다를 뿐 함수를 정의한다는 것은 모두 동일하다.
- 함수 선언문: 함수 리터럴과 형태가 동일하나, 함수 선언문에서는 함수 이름을 생략할 수 없다. 자바스크립트 엔진은 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고 거기에 함수 객체를 할당한다.
- 함수 표현식: 자바스크립트의 함수는 값의 성질을 가지는 일급 객체이다. 함수는 일급 객체이기에 함수 객체를 변수에 할당 가능하며, 이를 함수 표현식이라고 한다.
- Function 생성자 함수: 빌트인 함수인 Function 생성자 함수에 매개변수 목록과 함수 몸체를 문자열로 전달하여 new 연산자와 함께 호출하면 함수 객체를 생성하여 반환한다. 이 방식은 일반적이지 않고 바람직하지 않다. 함수 선언문, 함수 표현식 방식과 다르게 동작한다.
- 화살표 함수: ES6에서 도입되었고, 화살표를 사용하여 간략하게 함수 선언이 가능하며 이름을 생략하는 익명 함수로 항상 정의한다.
// 함수 선언문 (함수 이름 생략이 불가능하다)
function add(x, y) {
return x + y;
}
console.log(add(2, 5)); // 7
// 함수 표현식 (함수 이름 생략이 가능하다)
var add = function (x, y) {
return x + y;
}
console.log(add(2, 5)); // 7
// Function 생성자 함수
var add = new Function('x', 'y', 'return x + y');
console.log(add(2, 5)); // 7
// 화살표 함수
const add = (x, y) => x + y;
console.log(add(2, 5)); // 7
함수 생성 시점과 함수 호이스팅
함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출 가능하나, 함수 표현식으로 정의한 함수는 함수 표현식 이전에 호출 불가능하다. 이는 함수 선언문으로 정의한 함수와 함수 표현식으로 정의한 함수의 생성 시점이 다르기 때문이다.
함수 선언문 또한 런타임 이전에 자바스크립트 엔진에 의해 먼저 실행되어 함수 선언문 이전에 함수를 참조하며 호출할 수 있다. 함수 선언문이 코드의 선두로 끌어올려진 것처럼 동작하는 자바스크립트 고유의 특징이다. 이를 "함수 호이스팅(Function Hoisting)"이라고 한다.
반면, 변수 할당문의 값은 할당문이 실행되는 시점인 런타임에 평가되기에 함수 표현식의 함수 리터럴은 할당문이 실행되는 시점에 평가되어 함수 객체가 된다. 즉, 함수 표현식으로 함수를 정의하면 함수 호이스팅이 아니라 변수 호이스팅이 발생하는 것이다.
함수 호이스팅은 함수 호출 전 함수를 선언해야 한다는 규칙을 무시하기에 함수 표현식을 사용할 것이 권장된다.
함수 호출하기
함수는 함수를 가리키는 식별자와 한 쌍의 소괄호인 함수 호출 연산자로 호출할 수 있다.
매개변수와 인수
함수를 실행하기 위해 필요한 값을 함수 내부로 전달해야 하는 경우. 매개변수를 통해 인수를 전달한다. 인수의 개수와 타입에는 제한이 없고 인수는 값으로 평가될 수 있는 표현식이면 된다. 매개변수는 함수 몸체 내부에서만 참조할 수 있다.
인수 확인
함수를 정의한 개발자의 의도와 달리, 적절하지 않은 인수가 전달되어 오류를 발생시킬 수 있다. 이를 해결하는 방법으로는 타입스크립트와 같은 더 엄격한 상위 확장 언어를 도입할 수도 있고, 단축 평가를 사용하여 매개변수에 기본값을 할당할 수도 있다.
매개변수의 최대 개수
매개변수의 최대 개수에 대해 ECMAScript 사양은 명시적으로 제한은 두진 않지만, 매개변수는 코드를 이해하는데 방해되는 요소이기에 매개변수는 가능한 적은 것이 좋다. 매개변수에는 순서가 있고 함수의 사용법을 이해하기 어렵게 만들어 에러를 발생시킬 가능성을 높인다.
매개변수가 많다는 것은 함수가 여러 가지 일을 한다는 것이고 이상적인 함수는 "한 가지 일만 하는 것"이다. 따라서 매개변수는 최대 3개 이상을 넘지 않는 것이 좋다.
반환문
함수는 return 키워드와 표현식을 통해 실행 결과를 함수 외부로 반환할 수 있다. 반환문을 두 가지 역할을 한다.
- 반환문은 함수의 실행을 중단하고 함수 몸체를 빠져나간다. (반환문 이후 다른 문이 존재하면 그 문은 무시된다.)
- 반환문은 return 키워드 뒤에 오는 표현식을 평가해 반환한다. (return 키워드 뒤에 표현식이 명시적으로 지정되지 않으면 undefined가 반환된다.)
반환문은 생략할 수 있고, 함수 몸체 내부에서만 사용할 수 있다. 이러한 주의점들을 잘 고려하여 반환문을 작성해야 한다.
다양한 함수들
즉시 실행 함수
함수 정의와 동시에 즉시 호출되는 함수이며, 단 한 번만 호출되며 재호출이 불가능한 함수이다. 즉시 실행 함수는 그룹 연산자()로 감싸야 한다.
재귀 함수
자기 자신을 호출하는 함수를 재귀 함수라고 한다. 반복되는 처리를 반복문을 사용하지 않고 재귀 호출로 대신할 수 있다.
중첩 함수
함수 내부에 정의된 함수를 중첩 함수라고 한다. 중첩 함수를 포함하는 함수를 외부 함수라 하며, 중첩 함수는 외부 함수 내부에서만 호출 가능하다.
콜백 함수
함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백 함수라고 한다. 매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 고차 함수라고 한다. 고차 함수는 콜백 함수를 자신의 일부분으로 합성한다.
콜백 함수는 고차 함수에 의해 호출되며 고차 함수는 필요에 따라 콜백 함수에 인수를 전달할 수 있다.
순수 함수와 비순수 함수
어떤 외부 상태에 의존하지 않고 변경하지 않는 "부수 효과"가 없는 함수를 순수 함수라고 하며, 부수 효과가 있는 함수를 비순수 함수라고 한다.
함수가 외부 상태를 변경하면 상태 변화를 추적하기 어렵기에 비순수 함수 사용을 최대한 줄이고 순수 함수를 사용하는 것이 좋다.
래퍼런스(Reference)
https://www.yes24.com/Product/Goods/92742567