일련의 과정을 statement로 구현하고, 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것.
함수는 객체 타입의 값으로, 이름(식별자)을 붙일 수 있다 (코드의 가독성을 위해 중요)
// 1) 함수 선언문 (함수 이름을 생략할 수 없음)
function add(x, y) { // 함수이름: add, 매개변수: x, y
return x + y; // 반환값
};
// 2) 함수 표현식 (함수 리터럴) (설명 1-2)
// 변수에 함수 리터럴 할당 (함수 리터럴은 평가되어 값을 생성 = 함수는 호출 가능한 객체다)
const add = function(x, y) {…};
// 3) function 생성자 함수 (바람직하지 않음)
const add = new Function(‘x’, ‘y’, ‘return x + y’);
// 4) 화살표 함수(ES6) (설명 1-4)
const add = (x, y) => x + y; // 항상 익명함수로 정의
함수를 가리키는 식별자와 한 쌍의 소괄호인 함수 호출 연산자로 호출. 0 개 이상의 인수를 쉼표로 구분해 나열.
함수를 호출하면, 현재 실행 흐름을 중단하고, 호출된 함수로 실행 흐름을 옮김.
// 함수 호출 (설명 2-1)
add(2, 5); // 인수: 2, 5 // 결과: 7 (함수명이 아닌, 함수를 가리키는 식별자 add로 호출)
// 함수 참조
console.dir(add); // f add(x, y). // 함수 객체의 프로퍼티까지 출력
// 인수 타입 확인
function add(x, y) {
if (typeof x !== ‘number’ || typeof y !== ‘number’) {
throw new Error(‘인수는 모두 숫자값이어야 함’);
}
return x + y;
}
add(‘a’, ‘b’); // TypeError: 인수는 모두 숫자값이어야 함
// 인수 초기화
function add(a = 0, b = 0) {
return a + b;
}
add(); // 0
함수 정의와 동시에 즉시 호출되는 함수. (Immediately Invoked Function Expression)
단 한번만 호출되며, 다시 호출할 수 없다.
// 즉시 실행 함수
// () 그룹 연산자로 함수를 묶어서 함수 리터럴을 평가해 함수 객체를 생성해야 함.
(function () { // 익명 함수를 사용하는 것이 일반적
const a = 3;
const b = 5;
return a + b;
}());
// 함수 리터럴로 평가되며, 함수 이름은 함수 몸체 내에서만 참조할 수 있으므로 재호출 불가.
(function foo() {...}());
foo(); // Reference Errorr: foo is not defined
// 일반 함수처럼 값을 반환하고, 인수를 전달할 수 있다.
const res = (function (a, b) {
return a * b;
}());
res(3, 5); // 15
자기 자신을 호출하는 함수. 반복문 없이 구현 가능.
무한 재귀 호출이므로, 재귀 호출을 멈출 수 있는 탈출 조건이 반드시 필요.
반복문보다 재귀함수를 사용하는 것이 더 직관적으로 이해하기 쉬울 때만 사용하기.
function factorial(n) {
// escape 조건
if (n <= 1) return 1;
return n * factorial(n - 1); // 함수 내부에서 함수명을 사용해 자기 자신 호출 가능
}
factorial(3); // 3 * 2 * 1 = 6
함수 내부에 정의된 함수로, 일반적으로 외부 함수(중첩 함수를 포함하는 함수)를 돕는 헬퍼 함수의 역할을 한다. (중첩 함수는 외부 함수 내에서만 호출 가능)
function outer() {
const x = 1;
// 중첩 함수
function inner() {
const y = 2;
console.log(x + y); // 외부 함수의 변수 참조 가능
}
inner();
}
outer();
함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수.
로직의 일부를 함수로 전달받아 수행하므로 더욱 유연한 구조를 갖게 된다.
콜백함수는 고차함수(사용처)에 의해 호출되며, 고차함수는 필요에 따라 콜백 함수에 인수를 전달할 수 있다.
// 외부에서 func이라는 함수 매개변수 전달받음 (= 고차함수)
// 고차함수는 콜백 함수를 자신의 일부분으로 합성
function repeat(num, func) {
for (let i = 0; i < num; i++) {
// 경우에 따라 변경되는 일을 함수 func로 추상화
func(i); // i를 전달하면서 func 호출
}
}
// 콜백 함수 (=헬퍼 함수)
const logOdds = function(num) {
if (i % 2) console.log(i);
}
// 외부에서 함수를 인수로 전달해줌
repeat(5, logOdds); // 1, 3
// 콜백함수가 고차함수 내에서만 사용된다면, 콜백함수를 익명 함수 리터럴로 정의&전달
repeat(5, function (i) {
if (i % 2) console.log(i);
})
// 콜백함수를 사용한 이벤트 처리
document.getElementById('myButton').addEventListener('click', function() {...});
// 콜백함수를 사용한 비동기 처리
setTimeout(function () {
console.log('1초 경과');
}, 1000);
// 배열 고차 함수에서도 사용됨 (ex. map, filter, reduce)
// 콜백 함수를 사용하는 고차함수 map
const res = [1, 2, 3].map(function (item) {
return item * 2;
})
console.log(res); // [2, 4, 6]
- 순수 함수 - 어떤 외부 상태에 의존하지도, 변경하지도 않는, 부수효과가 없는 함수.
- 비순수 함수 - 외부 상태에 의존하거나 외부 상태를 변경하는, 부수효과가 있는 함수.
let count = 0;
// 순수 함수
function increase(n) {
return ++n;
}
// 순수 함수가 반환한 값을 변수에 재할당해 상태 변경
count = increase(count); // 1
// 비순수 함수
function increase2() {
return ++count; // 외부 상태에 의존하며 외부 상태 변경
}
// 비순수 함수는 외부 상태(count)를 변경하므로 상태 변화를 추적하기 어려워짐
increase2(); // 2