2024. 1. 24. 02:38ㆍ개발/Deep Dive (JS) 정리
12.1 함수란?
프로그래밍 언어의 함수는 수학의 함수와 같은 개념이다. 일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것이다. 함수 내부로 입력을 전달받는 변수를 매개 변수(parameter), 입력을 인수(argument), 출력을 반환값(return value)이라 한다. 함수는 값이며, 특정 함수를 구별하기 위해 식별자인 함수 이름을 사용할 수 있다.
12.2 함수를 사용하는 이유
코드를 재사용하기 위해 사용한다. 재사용성을 높이는 함수는 코드의 중복을 억제하고 유지보수의 편의성을 높이고 실수를 줄여 코드의 신뢰성을 높이는 효과가 있다.
변수 이름과 마찬가지로 함수 이름 또한 함수 자신의 역할을 잘 설명해야 하고 이는 함수 내부 코드를 이해하지 않고도 함수의 역할을 파악할 수 있게 하여 코드의 가독성을 향상시킨다. 가독성이 높은 코드가 좋은 코드다.
12.3 함수 리터럴
자바스크립트의 함수는 객체 타입의 값이다. 따라서 함수 리터럴로 생성할 수 있다. 함수 리터럴은 function 키워드, 함수 이름, 매개 변수 목록, 함수 몸체로 구성된다.
//변수에 함수 리터럴을 할당
var f = function add(x, y) {
return x + y;
}
- 함수 이름
- 함수 이름은 식별자다. 따라서 식별자 네이밍 규칙을 준수해야 한다.
- 함수 이름은 함수 몸체 내에서만 참조할 수 있는 식별자다.
- 함수 이름은 생략할 수 있다. 이름이 있는 함수를 기명 함수, 이름이 없는 함수를 무명/익명 함수라 한다.
- 매개변수 목록
- 0개 이상의 매개변수를 소괄호로 감싸고 쉼표로 구분한다.
- 각 매개변수에는 함수를 호출할 때 지정한 인수가 순서대로 할당된다. 즉, 매개변수 목록은 순서에 의미가 있다.
- 매개변수는 함수 몸체 내에서 변수와 동일하게 취급된다. 따라서 매개변수도 변수와 마찬가지로 식별자 네이밍 규칙을 준수해야 한다.
- 함수 몸체
- 함수가 호출되었을 때 일괄적으로 실행될 문들을 하나의 실행 단위로 정의한 코드 블록이다.
- 함수 몸체는 함수 호출에 의해 실행된다.
함수는 객체지만 일반 객체와는 다르게 호출할 수 있다. 함수가 객체라는 사실은 다른 프로그래밍 언어와 구별되는 자바스크립트의 중요한 특징이다.
12.4 함수 정의
함수 정의란 함수를 호출하기 이전에 인수를 전달받을 매개변수와 실행할 문들, 그리고 반환할 값을 지정하는 것을 말한다. 정의된 함수는 자바스크립트 엔진에 의해 평가되어 함수 객체가 된다.
12.4.1 함수 선언문
//함수 선언문
function add(x, y) {
return x + y;
}
console.log(add(2,5)); // 7
함수 선언문은 함수 리터럴과 형태가 동일하다. 단, 함수 리터럴은 함수 이름을 생략할 수 있으나 함수 선언문은 함수 이름을 생략할 수 없다.
//함수 선언문은 함수 이름을 생략할 수 없다.
function (x, y) {
return x + y;
}
//SyntaxError: Function statements require a function name
자바스크립트 엔진은 { }(중괄호)처럼 중의적인 코드는 코드의 문맥에 따라 해석을 다르게 한다. { }이 단독으로 존재하면 자바스크립트 엔진은 블록문으로 해석하고 { }이 값으로 평가되어야 할 문맥에서 피연산자로 사용되면 객체 리터럴로 해석한다.
자바스크립트 엔진은 함수 선언문을 해석해 함수 객체를 생성한다. 이때 함수 이름은 함수 몸체 내부에서만 유효한 식별자이므로 함수 이름과는 별도로 생성된 함수 객체를 가리키는 식별자가 필요하다. 함수 객체를 가리키는 식별자가 없으면 생성된 함수 객체를 참조할 수 없으므로 호출할 수도 없다. 따라서 자바스크립트 엔진은 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 거기에 함수 객체를 할당한다.
함수는 함수 이름으로 호출하는 것이 아니라 함수 객체를 가리키는 식별자로 호출한다. 자바스크립트 엔진은 함수 선언문을 아래에서 말할 함수 표현식으로 변환해 함수 객체를 생성한다고 생각할 수 있다. 그러나 함수 선언문과 함수 표현식이 정확히 동일하게 동작하는 것은 아니다.
12.4.2 함수 표현식
//함수 표현식
var add = function (x, y) {
return x + y;
}
console.log(add(2,5)); // 7
자바스크립트의 함수는 값처럼 변수에 할당할 수 있는 일급 객체다. 이와 같이 함수를 변수에 할당하는 방식을 함수 표현식이라 한다. 함수 표현식의 함수 리터럴은 함수 이름을 생략하는 것이 일반적이다.
//기명 함수 표현식
var add = function foo (x, y) {
return x + y;
}
//함수 객체를 가리키는 식별자로 호출
console.log(add(2,5)); // 7
//함수 이름으로 호출하면 ReferenceError가 발생한다.
//함수 이름은 함수 몸체 내부에서만 유효한 식별자다.
console.log(foo(2,5)); // ReferenceError: foo is not defined
12.4.3 함수 생성 시점과 함수 호이스팅
함수가 생성된 시점에 어떻게 호이스팅 되는지에 따라 함수 선언문과 함수 표현식의 차이점을 알 수 있다.
//함수 호출
console.log(add(2, 5)); // 7
console.log(sub(2, 5)); // TypeError: sub is not a function
//함수 선언문
function add(x, y) {
return x + y;
}
//함수 표현식
var sub = function (x, y) {
return x - y;
};
결론을 먼저 이야기 하자면 함수 선언문은 함수 호이스팅이 이루어지고 함수 표현식은 변수 호이스팅이 일어난다.
함수 선언문으로 함수를 정의하면 런타임 이전에 함수 객체가 먼저 생성된다. 그리고 자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고 생성된 함수 객체를 할당한다. 이를 통해 함수 선언문이 코드의 선두로 끌어올려진 것처럼 동작하는 자바스크립트 고유의 특징을 함수 호이스팅이라 한다.
함수 표현식으로 함수를 정의하면 변수에 함수 리터럴로 생성한 함수 객체를 할당한다. 이를 var 키워드로 선언하게 될 경우, 런타임 이전에 자바스크립트 엔진에 의해 먼저 실행되어 식별자를 생성하고 선언된 변수는 undefined로 초기화된다. 이는 변수 호이스팅이고 함수 리터럴이 값으로 할당된 변수에서 변수 할당문의 값은 할당문이 실행되는 시점에 평가되어 함수 객체가 된다. ES6에 도입된 let, const 키워드는 호이스팅은 되지만 변수가 선언되는 과정인 선언->초기화 과정에서 선언은 되지만 초기화는 진행되지 않아 실질적으로는 호이스팅이 발생하지 않는 것처럼 동작한다.
함수 호이스팅은 함수를 호출하기 전에 반드시 함수를 선언해야 한다는 당연한 규칙을 무시한다. 따라서 함수 선언문 대신 함수 표현식을 사용할 것을 권장한다.
12.4.4 Function 생성자 함수
자바스크립트가 기본 제공하는 빌트인 함수인 Function 생성자 함수에 매개변수 목록과 함수 몸체를 문자열로 전달하면서 new 연산자와 함께 호출하면 함수 객체를 생성해서 반환한다. new 연산자 없이 호출해도 결과는 동일하다.
var add = new Function('x', 'y', 'return x+y');
console.log(add(2, 5)); // 7
하지만 이러한 Function 생성자 함수로 함수를 생성하는 방식은 일반적이지 않고 바람직하지도 않다. 해당 방법으로 함수를 생성할 수 있다는 사실만 알 수 있도록 하자.
12.4.5 화살표 함수
ES6에서 도입된 함수 선언 방식으로 function 키워드 대신 화살표 => 를 사용해 좀 더 간략한 방법으로 함수를 선언할 수 있다. 화살표 함수는 항상 익명 함수로 정의한다.
//화살표 함수
const add = (x, y) => x + y;
cosole.log(add(2,5)); // 7
'개발 > Deep Dive (JS) 정리' 카테고리의 다른 글
[JS] 09장 타입 변환과 단축 평가-모던 자바스크립트 Deep Dive (1) | 2024.02.01 |
---|---|
[JS] 13장 스코프-모던 자바스크립트 Deep Dive (1) | 2024.01.27 |
[JS] 08장 제어문-모던 자바스크립트 Deep Dive (0) | 2024.01.15 |
[JS] 07장 연산자-모던 자바스크립트 Deep Dive (1) | 2024.01.15 |
[JS] 06장 데이터 타입-모던 자바스크립트 Deep Dive (2) | 2024.01.09 |