on
[Javascript]함수(2)
함수 호출과 값
1. 함수 호출
const add = function (x, y) {
return x + y;
};
add(1, 2); // 함수 호출
위 예시에서 처럼 함수 식별자를 소괄호 쌍과 함께 호출하고, 매개 변수가 있다면 소괄호 안에 인자로 함께 넣어 호출한다.
함수를 호출하면 현재의 스크립트 실행 흐름을 중단하고 호출된 함수로 실행 흐름을 옮긴다.
1) 매개변수와 인수
함수를 실행할 때 필요한 값들을 함수 외부에서 함수 내부로 전달할 필요가 있을 경우, 매개변수를 통해 인수를 전달한다. 또 매개변수에는 갯수와 타입에 제한이 없다. 그외의 특징들을 살펴보자.
- 매개변수는 함수 몸체 내부에서 변수와 동일하게 취급된다. 즉, 함수가 호출되면 매개변수를 생성하고
undefined
로 초기화한 후, 전달된 인수를 순서대로 할당한다.
// 함수 선언문
function add(x, y) {
return x + y;
}
// 함수 호출
// 인수 1과 2는 매개변수 x와 y에 순서대로 할당되고 함수 몸체의 문들이 실행된다.
var result = add(1, 2);
- 매개변수는 함수 내부에서만 참조할 수 있다. 즉, 매개변수의 스코프는 함수 내부다.
function add(x, y) {
console.log(x, y); // 2 5
return x + y;
}
add(2, 5);
console.log(x, y); // ReferenceError: x is not defined
- 매개변수에 비해 인수가 부족하다면, 매개변수에는 초기화되었던
undefined
값을 그대로 유지한다.(에러가 발생하지 않으니 유의)
function add(x, y) {
console.log(x, y); // 2 undefined
return x + y;
}
add(2, 5);
- 매개변수에 비해 인수가 많다면 초과된 이수는 무시된다.(그냥 버려지는 것은 어니다
arguments
객체의 프로퍼티로 보관은 되어있다.)
function add(x, y) {
// Arguments(3) [2, 5, 10, callee: ƒ, Symbol(Symbol.iterator): ƒ]
return x + y;
}
console.log(add(2, 5, 10)); // 7
2) 인수 확인
자바스크립트는 동적 타입 언어다. 따라서 매개변수의 타입을 사전에 지정할 수 없고, 심지어 매개변수와 인수의 갯수가 맞는지조차 체크하지 않는다. 따라서 넘어온 인수가 적절한지 확인할 필요가 있다.
function add(x, y) {
return x + y;
}
console.log(add(2)); // NaN : 갯수가 틀림
console.log(add("a", "b")); // 'ab' : type이 틀림
function add(x, y) {
if (typeof x !== "number" || typeof y !== "number") {
// 매개변수를 통해 전달된 인수의 타입이 부적절한 경우 에러를 발생시킨다.
throw new TypeError("인수는 모두 숫자 값이어야 합니다.");
}
return x + y;
}
console.log(add(2)); // TypeError: 인수는 모두 숫자 값이어야 합니다.
console.log(add("a", "b")); // TypeError: 인수는 모두 숫자 값이어야 합니다.
만약에 런타임에 에러 발생이 아닌 사전에 잘못된 호출을 막고 싶다면 자바스크립트의 상위 확장 버전인 타입스크립트를 사용하는 방법이 있다. (사랑해요 타입스크립트)
매개변수와 인수의 갯수가 맞지 않는 문제는 단축 평가 또는 ES6부터 도입된 매개변수의 기본값을 사용하여 undefined
를 방지할 수 있다.
//단축 평가
function add(a, b, c) {
a = a || 0;
b = b || 0;
c = c || 0;
return a + b + c;
}
//기본값 설정
function add(a = 0, b = 0, c = 0) {
return a + b + c;
}
console.log(add(1, 2, 3)); // 6
console.log(add(1, 2)); // 3
console.log(add(1)); // 1
console.log(add()); // 0
3) 매개변수의 최대 개수
위에서 얘기 했든 매개변수의 개수에는 제한이 없으나, 메모리 문제라던지와 같은 물리적 한계로가 있으므로 자바스크립트 엔진마다 매개변수의 최대 개수의 제한이 사실 있다. 하지만 이 개수의 충분히 많은 숫자이다. 그렇다고 매개변수를 많이 만드는게 과연 좋은 일일까? 매개변수는 순서에 따라 인수를 할당받으므로 가독성, 유지보수, 에러 등을 발생 시킬 요인이 많아지므로 최대한 적게 사용하는 것이 좋다.
매개변수는 0개에 가까울 수록 좋다.
만약 3개 이상 넘어간다면 객체로 만들어서 1개의 인수로 전달하는 것이 좋다.
//Bad
function signUp(name, age, email, password, address, gender){
...
}
signUp("홍길동",18,"test@gmail.com","*********","서울시 서초구 방배동", "male");
//Good
function signUp({name, age, email, password, address, gender}){
...
}
const userInfo = {
name:"홍길동",
age:18,
email:"test@gmail.com",
password:"*********",
address:"서울시 서초구 방배동",
gender:"male"
};
signUp(userInfo);
객체를 인수로 넘길 경우, 매개변수의 순서를 신경쓰지 않아도 되고, 인수로 전달할 때 키 값으로 인해 명시적으로 해당 값의 의미를 표현할 수 있다. 다만, 함수 외부에서 함수 내부로 객체를 인수로 전달할 경우, 함수 내부에서 객체의 값을 변경할 경우 함수 외부 객체의 값도 변경된다는 점을 유의하자.
2.반환문
함수는 return
키워드와 반환값으로 이뤄진 반환문을 사용해 함수의 실행 결과를 함수 외부로 반환하는 것이다.
function multiply(x, y) {
return x * y; // 반환문
}
// 함수 호출은 반환값으로 평가된다.
var result = multiply(3, 5);
console.log(result); // 15
반환문은 2가지 역할을 한다.
- 반환문은 함수의 실행을 중단하고 함수 몸체를 빠져 나간다. 따라서 반환문 이후에 다른 문이 존재하면 그 문은 실행되지 않는다.
function multiply(x, y) {
return x * y; // 반환문
// 반환문 이후에 다른 문이 존재하면 그 문은 실행되지 않고 무시된다.
console.log("실행되지 않는다.");
}
console.log(multiply(3, 5)); // 15
- 반환문은
return
키워드 뒤의 표현식을 평가해 반환한다. 만약 표현식을 명시적으로 지정하지 않으면undefined
가 반환된다. 또한 반환문을 생략하더라도 암묵적으로undefined
를 반환한다.
function foo() {
return;
}
console.log(foo()); // undefined
function foo() {}
console.log(foo()); // undefined
반환문은 함수 몸체 내부에서만 사용할 수 있음을 유의한다. 전역에서 사용할 경우 에러가 발생한다. (Node.js는 파일 스코프를 가지므로 에러가 발생하지 않는다.)