함수는 일련의 과정을 문(statement) 로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것.
함수의 구성:
자바스크립트 함수의 특징:
함수를 정의하는 방법에는 4가지가 있다.
//함수 선언문
function add(x,y) {
return x+y;
}
//함수 표현식
var add = function (x,y) {
return x+y;
};
//Function 생성자 함수
var add = new Function ('x','y','return x+y');
//화살표 함수
var add = (x,y) => x+y;
참고로 함수는 '정의(definitioon)'한다고 표현한다. 변수는 '선언(declaration)'이라고 표현하는 반면에 말이다. ( 함수는 일단 함수 선언문이 평가되면 식별자가 암묵적으로 생성되고 함수 객체가 할당되기 때문에 선언 후 할당까지 이뤄진 상태이기 때문인듯.)
함수 선언문 vs. 함수 (리터럴) 표현식 🌟
1) 함수 선언문은 함수 이름을 생략할 수 없다.
반면, 함수 표현식은 변수에 값으로 함수를 할당시키는 것이다. 따라서 함수 이름을 생략할 수 있다. 함수 표현식의 경우 함수명이 아닌 변수명으로 식별자를 고르기 때문이다. 🌟
이렇게 변수명을 대신 사용하기 때문에 함수 이름을 생략한다. 이렇게 변수명만 있고 함수명은 생략된 함수를 "익명 함수", 생략 안한 것은 "기명 함수" 라고 한다.
//함수 표현식 (익명)
var add = function (x,y) {
return x+y;
};
//함수 표현식 (기명)
var add = function add (x,y) {
return x+y;
};
2) 함수 선언문은 표현식이 아닌 문이다. 즉, 값으로 쓸 수 없다.
반면 함수 표현식은 표현식인 문이므로 값으로 사용 가능하다.
3) 또 함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출할 수 있다. 즉, 함수 호이스팅이 발생한다. (* 모든 선언문은 런타임 이전에 먼저 실행된다.) 🌟
하지만 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생한다. 즉, 변수 선언은 런타임 이전에 되지만, 변수 값 할당은 런타임에 평가되기 때문에, 함수 표현식 이전에 호출한 값은 undefined 로 평가되며 이 때 함수를 호출하면 TypeError 가 발생하게 된다.🌟
Function 생성자 함수
화살표 함수
함수 호출은 식별자와 함수 호출 연산자인 한 쌍의 소괄호() 로 호출한다.
// 함수 선언
function add (x,y) {
return x+y;
}
//함수 호출
var result = add(1,2);
함수를 실행하기 위해 필요한 값을 외부에서 함수 내부로 전달할 필요가 있는 경우, 매개변수를 통해 인수를 전달한다. 인수는 값으로 평가될 수 있는 표현식이어야 한다. 인수는 함수를 호출할 때 지정하며, 개수와 타입에 제한이 없다.
함수는 매개변수와 인수의 개수가 일치하는지 체크하지 않는다. 인수가 부족해서 인수가 할당되지 않은 매개변수의 값은 undefined 이며, 인수가 더 많은 경우 초과된 인수는 무시된다. 이렇게 무시된 인수는 버려지는 것이 아니라 암묵적으로 argu 객체의 프로퍼티로 보관되며 나중에 가변 인자 함수를 구현할 때 사용된다.(18장)
또 자바스크립트는 동적 타입 언어다. 따라서 자바스크립트 함수는 매개변수의 타입을 사전에 지정할 수 없다. 따라서 자바스크립트의 경우 함수를 정의할 때 적절한 인수가 전달되었는지 확인할 필요가 있는데 p.171 과 같은 코드를 직접짜거나 자바스크립트 상위 확장 버전인 타입스크립트를 도입해서 컴파일 시점에 부적절한 호출을 방지할 수 있게 한다.
매개변수는 최대 3개 이상 넘지 않는 것을 권장한다.
함수는 return 키워드와 표현식(반환값) 을 사용해 함수 실행 결과를 외부로 반환(return) 할 수 있다.
반환문의 2가지 역할 🌟:
function foo () {
return;
}
console.log(foo()); // undefined
크게 4가지로 나눌 수 있다: 즉시 실행 함수, 재귀 함수, 중첩 함수, 콜백 함수
즉시 실행 함수: 함수 정의와 동시에 즉시 호출되는 함수.
(function () {}() ); 혹은
(function (){})(); 혹은
!function (){}(); 혹은
+function(){}(); 로 표현한다.
```
재귀 함수: 자기 자신을 호출하는 함수. 보통 반복문 대신 쓰일 때 사용한다. 재귀 호출을 멈출 수 있는 탈출문을 반드시 만들어야 한다. 그렇지 않으면 재귀함수가 무한호출되어 스택 오버플로 에러가 발생한다.
var factorial = function foo (n) {
//탈출 조건 n 이 1 일 때 재귀호출을 멈춘다.
if (n <= 1) return 1;
// otherwise, 재귀 호출
return n * factorial(n-1);
};
중첩 함수(또는 내부 함수): 함수 안의 함수. 반대로 이러한 중첩함수를 포함하는 함수는 "외부 함수" 라고 한다. 중첩함수는 주로 외부함수를 돕는 헬퍼함수 역할을 한다.
콜백 함수🌟: 함수의 매개 변수를 통해 다른 함수의 내부로 전달되는 함수. 반면 매개 변수를 통해 함수의 외부에서 콜백함수를 전달받은 함수를 "고차 함수🌟" 라고 한다. 고차 함수는 콜백 함수의 호출 시점을 결정해서 호출하며, 함수에 콜백 함수를 전달할 떄 콜백 함수를 호출하지 않고 함수 자체를 전달해야 한다.
// 외부함수 repeat. 외부에서 전달받은 함수f(콜백함수)를 n만큼 반복호출한다.
function repeat (n,f) {
for (var i=0; i < n; i++) {
f(i);
}
};
// 소환될 함수(콜백함수)1
var logAll = function (i) {
console.log(i);
};
// 소환될 함수(콜백함수)2
var logOdd = function (i) {
if (i % 2) console.log(i);
};
// 반복 호출할 함수를 인수로 전달한다.
repeat ( 5, logAll); // !주의: logAll() 아님. logAll 임.
repeat ( 5, logOdd); // 여기도 마찬가지. 콜백함수는 호출 x, 함수 자체 전달.