함수는 쉽게 생각하면 입력을 받고 처리하여 출력을 해주는 것이다. 이번 글에서는 함수의 입력과 출력에 대해 좀 더 자세히 알아보고자 한다.
매개변수와 인수
함수 외부에서 함수 내부로 값을 전달할 필요가 있는 경우 매개변수를 통해 인수로 값을 전달한다. 예를 들어 더하기 함수를 만든다고 가정하자. 이 함수는 더할 2개의 수를 필요로 한다. 그러므로 함수를 정의할 때 a, b라는 매개변수를 입력으로 받을 수 있도록 정의한다. 그리고 실제 호출할 때 더할 2개의 값을 인수로 넣어준다.
function add(a ,b){
return a + b;
}
console.log(add(10, 12)); // 22
함수가 호출되면 함수 내부에서 매개변수가 생성되고 undefined로 초기화 된다. 그리고 인자로 들어온 값들은 차례로 할당한다. 위 그림에서 add(10, 12) 를 통해 함수를 호출하면 함수 내부에 a, b라는 변수가 만들어지고 undefined로 초기화된다. 그리고 인수로 넘겨받은 10과 12를 각각 a와 b에 할당해준다. 매개변수의 스코프는 함수 내부이다.
자바스크립트에서 함수는 매개변수와 인수의 개수가 일치하는지 체크하지 않는다. 만약 인수가 부족하면 인수를 할당받지 못한 매개변수는 undefined로 남아 있는다. 반대로 인수가 매개변수보다 많으면 초과된 인수는 무시된다. 아래 그림을 통해 살펴볼 수 있다.
function add(a ,b){
return a + b;
}
console.log(add(10)); //NaN
console.log(add(1, 2, 4)); //3
아래의 예제는 매개변수를 통해 전달된 인자의 타입을 체크하고 default 값을 넣어주는 로직을 추가한 것이다.
function add(a ,b){
if(typeof a !== "number" || typeof b !== "number"){
throw new TypeError("인수가 숫자가 아닙니다.");
}
return a + b;
}
console.log(add(10, "1")); //TypeError: 인수가 숫자가 아닙니다.
function add(a = 1 ,b = 1){
return a + b;
}
console.log(add(10)); //b매개변수에 기본값 1이 전달되어 11이 출력된다.
반환문(RETURN 문)
자바스크립트 함수에서 반환 문은 두 가지 역할을 한다.
- 반환 문은 함수의 실행을 종료하고 함수 몸체를 빠져나가 함수를 호출했던 컨텍스트로 돌아간다. 그러므로 함수 반환 문 이후에 있는 코드는 실행되지 않는다.
- 반환 문은 return 키워드 뒤에 오는 표현식을 평가해 반환한다. return 키워드 뒤에 반환 값으로 사용할 표현식을 쓰지 않으면 undefined가 반환된다. 우리의 예제에서는 a + b를 한 값을 반환하고 있다.
객체를 인수로 전달할 때 주의점
function changeValue(value, obj){
value = value * 2;
obj.name = 'PARK';
}
let num = 10;
let person = {
name : 'JIHO'
}
console.log(num); // 10
console.log(person.name); // JIHO
changeValue(num, person);
console.log(num); // 10
console.log(person.name); // PARK
위의 그림을 보면 changeValue 함수의 인수로 정수형 변수 num과 객체를 가리키는 변수 person을 넘겨주었다. 그리고 함수 내부에서 전달받은 값들은 변경해주었다. 다시 값을 확인했을 때 num 변수는 변함이 없었으나 person은 변화된 걸 확인할 수 있다. 왜 이런 결과가 나온 것일까? 차례대로 따라가 보겠다.
- changeValue 변수를 생성한다. 이 변수는 함수 객체를 가리키고 있다. 결국 changeValue함수를 생성하는 것이다.
- num, person 변수를 만들고 값을 할당해준다. num에는 10이 할당되고, person에는 name : "JIHO"를 프로퍼티로 가지는 객체를 가리키는 주소가 값으로 할당된다.
- num과 person을 인수로 넘겨주며 함수가 호출된다. 함수는 먼저 매개변수로 정의해 두었던 value와 obj 변수를 생성하고 undefined로 초기화 한다.
- value와 obj 변수에 인수로 넘어온 num과 person 변수의 값을 할당해준다. value에는 10이 할당되고, obj는 name : "JIHO"를 프로퍼티로 가지는 객체를 가리키는 주소가 할당된다.
- value에는 value * 2로 값을 변경해준다. obj는 obj가 가리키는 객체의 이름을 "PARK"으로 변경해준다.
즉시 실행 함수
함수 정의와 동시에 즉시 호출되는 함수를 즉시 실행 함수라고 한다. 즉시 실행 함수는 반드시 ( ) 감싼 후 실행해야 한다.
아래 그림을 보면 함수를 정의한 후 바로 실행하는 것을 확인할 수 있다.
let value = (function(){
let a = 10;
let b = 21;
return a * b;
}());
let result = (function(a ,b){
return a + b;
}(3, 4));
console.log(`value : ${value}, result : ${result}`); //value : 210, result : 7
중첩 함수
우리는 함수 내부에 또 다른 함수를 정의하여 사용할 수 있다. 이처럼 함수 내부에 정의된 함수를 중첩 함수 또는 내부 함수라 하고 중첩 함수를 포함하는 함수를 외부 함수라 한다. 일반적으로 중첩 함수는 자신을 포함하는 외부 함수의 일을 보조하는 역할을 한다.
function outFunc(){
let outNum = 1;
function inFunc(){
let inNum = 3;
console.log(inNum); // 3
console.log(outNum); // 1
}
inFunc();
}
outFunc();
위의 그림에서 outFunc 함수는 외부 함수이고 inFunc는 중첩 함수 또는 내부 함수이다. 위 예제에서 inFunc 함수 내부에서 outNum 변수를 출력하는 것을 주의 깊게 봐야 한다. inFunc 함수 내부에 outNum 변수가 없음에도 불구하고 error 없이 1이라는 값을 출력하고 있다. 왜냐하면 inFunc 함수 내부에 없는 outNum이라는 변수를 inFunc 함수의 상위 스코프에서 찾아오기 때문이다. 이러한 성질은 자바스크립트의 렉시컬 스코프 및 클로저와 연관이 있다. 지금은 '함수 내부에서 변수를 찾지 못하면 상위 스코프에서 찾는다.' 정도로만 알면 된다.
콜백 함수
콜백 함수란 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수이다. 매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 고차 함수라 한다. 내 개인적인 경험으로 자바스크립트를 사용할 때 콜백 함수를 이해하는 것은 무척 중요하며 아주 자주 사용한다. 자바스크립트에서는 함수가 일급 객체이기 때문에 함수를 매개변수의 인수로 넘겨줄 수 있다.
일급 객체란?
일급 객체(First-class Object)란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다.
- 변수에 할당 할 수 있다.
- 다른 함수의 인자로 전달될 수 있다.
- 다른 함수의 결과로서 리턴될 수 있다.
function introduce(f){
console.log("자기 소개를 해보겠습니다.");
f();
}
function JIHO(){
let name = "JIHO";
let age = 20;
console.log(`안녕하세요. 저는 ${name} 이고, 나이는 ${age}살 입니다.`);
}
function JIHYE(){
let name = "JIHYE";
let age = 23;
console.log(`안녕하세요. 저는 ${name} 이고, 나이는 ${age}살 입니다.`);
}
introduce(JIHO);
/*
자기 소개를 해보겠습니다.
안녕하세요. 저는 JIHO 이고, 나이는 20살 입니다.
*/
introduce(JIHYE);
/*
자기 소개를 해보겠습니다.
안녕하세요. 저는 JIHYE 이고, 나이는 23살 입니다.
*/
위의 그림을 보면 introduce, JIHO, JIHYE 함수를 정의하고 introduce 함수의 매개변수에 JIHO 함수와 JIHYE 함수를 인수를 넘겨주고 있다. 자바스크립트에서는 함수가 일급 객체이기 때문에 함수를 인수로 전달하는 것이 가능하다. JIHO, JIHYE 함수를 콜백 함수라 한다. 자바스크립트에서 콜백 함수는 비동기 처리나 DOM 요소의 이벤트 처리에 쓰인다.
introduce(function(){
let name = 'JINHO';
let age = 42;
console.log(`안녕하세요. 저는 ${name} 이고, 나이는 ${age}살 입니다.`);
});
/*
자기 소개를 해보겠습니다.
안녕하세요. 저는 JINHO 이고, 나이는 42살 입니다.
*/
위의 그림은 이름 없이 정의한 함수(익명 함수)를 introduce라는 고차 함수에 바로 전달하며 실행하고 있다. 콜백 함수를 위의 그림처럼 익명 함수로 정의 후 바로 전달해도 문제가 없다. 위와 같은 형식으로 쓰는 경우가 많이 있기 때문에 눈에 익혀 두어야 한다.