함수는 어떤 동작을 수행하기 위해 사용되는, 잘 정리된 재사용 가능한 코드 블록이에요. JavaScript에서 함수를 정의하는 방법은 여러 가지가 있어요. 여기서는 _함수 선언_과 _함수 표현식_을 살펴볼게요. 화살표 함수 같은 다른 방법은 다른 개념에서 다뤄요.
JavaScript에서 함수를 정의하는 표준적인 방법은 _함수 선언_이며, 함수 정의 또는 _함수 문_이라고도 해요.
function 키워드, 함수 이름, 그리고 괄호로 감싸여 쉼표로 구분된 매개변수 목록으로 구성돼요.
그 뒤에는 함수 본문(함수가 하는 일을 정의하는 문들의 모음)이 중괄호로 감싸여 이어져요.
function someName(param1, param2, param3) {
// ...
}
JavaScript에서는 함수 이름을 쓰고 그 뒤에 인자를 담은 괄호를 붙여서 함수를 호출해요.
someName(arg1, arg2, arg3);
JavaScript에서는 함수 이름만 쓴다고 해서 함수가 호출되지는 않아요.
function sayHello() {
console.log('Hello, World!');
}
sayHello;
// => [Function: sayHello]
// The text representations varies between environments.
sayHello();
// => 'Hello, World!'
함수 본문 안에서 매개변수를 다룰 때는 함수에 전달된 원래 값에 생길 수 있는 부작용을 염두에 두어야 해요. JavaScript에서 인자는 원래 값에 대한 참조를 복사한 것이에요. 이것이 실제로 무엇을 의미하는지는 인자의 데이터 타입에 따라 달라요.
원시 데이터 타입의 값은 _불변_이에요. 모든 "수정"은 항상 새로운 원시 값을 만들어요. 그렇기 때문에 함수 본문에서 인자에 무슨 일이 일어나더라도 원래 값은 영향을 받지 않아요.
const num = 0;
function increase(number) {
number = number + 1;
}
increase(num);
num;
// => 0
객체, 배열, 함수 같은 값은 달라요. 참조가 복사되기 때문에 재할당은 원래 값에 영향을 주지 않아요. 하지만 얕은 복사를 다루고 있기 때문에, 함수 본문에서 인자를 수정하면 전달된 원래 값도 함께 바뀌어요.
const nums = [0, 1, 2, 3, 4];
function pushFive(arr) {
arr.push(5);
}
pushFive(nums);
nums;
// => [0, 1, 2, 3, 4, 5]
기본적으로 JavaScript에서 함수 선언에 정의된 모든 매개변수는 선택 사항이에요.
함수에 매개변수보다 적은 수의 인자가 전달되면, 빠진 인자는 함수 본문 안에서 undefined가 돼요. Null과 Undefined를 참고해요.
많은 경우에 값이나 undefined가 전달되지 않았을 때 매개변수를 _기본값_으로 초기화하는 것이 더 합리적이에요.
이것은 함수 정의에서 직접 기본 매개변수를 지정하면 돼요.
function someName(param1 = defaultValue1, param2 = defaultValue2) {
// ...
}
함수는 함수 정의에 있던 매개변수보다 더 많은 인자로 호출될 수 있어요. 이런 초과 인자를 포함한 모든 인자는 arguments "배열"에서 찾을 수 있어요.
임의의 개수의 인자를 받는 함수(가변 인자 함수)를 정의할 수도 있어요. 자세한 내용은 Rest와 Spread 연산자의 나머지 매개변수를 참고해요.
return 문은 함수 실행을 끝내고 함수를 호출한 쪽에 반환할 값을 지정해요. 함수는 여러 개의 return 문을 가질 수 있어요.
function checkNumber(num) {
if (num === 0) {
return 'You passed 0, please provide another number.';
}
return 'Thanks for passing such a nice number.';
}
값을 return하지 않거나 return 문이 없는 함수의 결과는 undefined예요.
JavaScript에는 암시적인 return이 없어요.
function nakedReturn(a) {
a * 2;
return;
}
nakedReturn(1);
// => undefined
function noReturn(a) {
a * 2;
}
noReturn(1);
// => undefined
JavaScript에서는 정확히 하나의 값만 반환할 수 있어요. 더 많은 정보를 전달하고 싶다면, 먼저 그것을 하나의 덩어리로 합쳐야 해요. 보통 객체나 배열로요.
function divide(a, b) {
return {
quotient: Math.floor(a / b),
remainder: a % b,
};
}
함수 선언은 독립적인 문이에요. 하지만 때로는 다른 표현식의 일부로 함수를 정의하는 것이 도움이 돼요. 예를 들어 할당문에서, 함수의 매개변수(콜백)로, 또는 객체의 값으로 쓸 수 있어요. 이것은 함수 표현식으로 할 수 있어요. 문법은 함수 선언과 같지만, 함수 이름을 생략해서 _익명 함수_를 만들 수 있다는 점만 달라요.
const someFunction = function (param) {
// ...
};
someOtherFunction(function (param) {
// ...
});
const obj = {
someFunction: function (param) {
// ...
},
};
함수는 JavaScript에서 새로운 실행 컨텍스트를 만들어요. 함수 안에서 정의된 변수는 그 함수 밖에서 접근할 수 없어요. 하지만 상위 스코프(함수 자신이 정의된 스코프)에서 정의된 변수는 함수 안에서 접근할 수 있어요. 스코프에 대한 MDN 문서에서 이런 동작의 예를 볼 수 있어요.
JavaScript의 변수 스코프에 대해 더 알아보려면 클로저를 살펴봐요.