본문 바로가기
Study-Note/JavaScript

05. 자바스크립트 함수의 매개변수와 인수, 어떻게 동작할까?

by Ji-u 2021. 12. 31.

안녕하세요! 좋아요요정입니다. 

지난 게시글에서는 자바스크립트 함수의 정의와 함수 리터럴, 표현식과 선언문의 차이, 함수 호이스팅에 대하여 작성했습니다. 

이번 게시글에서는 함수의 매개변수와 인수에 대하여 알아보고 어떻게 동작하는지, 사용하는 방법에 대해 알아보겠습니다!  

 

 

 

매개변수와 인수

함수를 호출할 때 함수를 가리키는 식별자(함수이름)과 소괄호를 활용해 호출합니다.

함수이름(인자 목록)

함수가 호출되면 현재의 코드 실행 흐름을 중단하고, 호출된 함수로 실행 흐름을 옮깁니다.

이때 소괄호를 통해 입력한 값 인자 목록을 함수의 매개변수에 순서대로 할당이 되어 함수 실행 컨텍스트에 복제되어 매개 변수로 할당되어 집니다. 그리고 할당된 매개변수는 함수가 종료될 때 실행컨텍스트가 제거되고 콜스택이 제거되며 함께 제거됩니다.

 

 

이해를 돕기 위해 그림과 함께 예제를 한번 보겠습니다.

const x = 2;
const y = 3;

function add(a, b) {
	return a + b;
}

const result = add(x, y);

함수가 호출되기 전 콜스택입니다.

 

함수가 호출되면 함수이름과 저장된 힙주소가 할당되고, 실행된 add 함수의 스택영역이 생성됩니다.

 

함수 안의 코드블럭이 실행되고 리턴되는 값은 변수에 할당됩니다.

 

add함수가 종료되면 해당 콜스택도 제거됩니다.

원시타입의 값의 함수의 흐름을 함께 살펴보았습니다. 매개변수는 함수가 정의될 때 선언되며 함수 내부에서 변수와 동일하게 취급됩니다. 함수 내부에서 선언되는 지역변수들과 같이 말이죠. 매개변수는 함수 몸체 내부에서만 사용이 가능하고 외부에서는 접근이 불가능합니다. 

 

 

만약 매개변수에 객체타입을 전달하면 어떻게 될까요? 

const cat = {name: 'cookie', age: 2}
const addAge = 1;

function add(object, num) {
    object.age += num;
}

add(cat, addAge)

기존 오브젝트의 값이 바뀌는 것을 확인할 수 있습니다. 이는 객체 타입은 메모리에 값이 저장되는게 아닌, 객체를 가리키는 주소가 저장되어 있기 때문에 매개변수에 복제되는 과정에서 객체를 가리키는 주소가 복제되어 나타나는 현상입니다. 

그렇기 때문에 객체타입을 인자값으로 전달하는 경우, 기존 객체를 사용하는 동작인지, 원본 객체의 수정 없이 새로운 객체를 깊은 복제해서 사용되는 함수인지에 따라 주의해서 사용해야 합니다.

 

 

 


 

매개변수와 인수의 사용

1. 매개변수와 인수의 개수가 일치하는지 체크하지 않는다. 

함수는 매개변수의 개수와 인수의 개수가 일치하는지 체크하지 않습니다. 

매개변수보다 적은 인수가 들어오는 경우 전달되지 않은 부분은  undefined으로 활용됩니다.

매개변수보다 많은 인수가 들어오는 경우 초과된 인수는 내부적으로 arguments라는 객체로 저장되어 보관됩니다.

function add(x, y) {
	return x + y;
}

add(3) // NaN = 3 + undefined
add(5, 10, 15) // 15 = 5 + 10   *3번째 인수 15는 arguments객체에 저장됨

위 함수의 경우  arguments객체를 출력해보면 아래와 같이 확인할 수 있습니다.

arguments.length를 통해 전달받은 인수의 수량을 확인할 수 있습니다. 배열과 관련된 메서드는 사용할 수 없습니다.

 

 

 

2. 자바스크립트에서 매개변수와 인수는 데이터타입을 지정할 수 없습니다.

위에 주어진 add함수에 문자열을 전달하면 어떻게 될까요? 문자열의 더하기 연산이 되어 반환되어집니다. 그 외의 데이터타입이 들어와도 연산을 진행합니다. 연산이 불가능한 데이터타입이어도 진행됩니다. 입력받는 데이터타입을 지정할 수 없습니다.

그렇기 때문에 의도와 다른 연산으로 인한 오류를 방지하고자 함수를 생성할 때에는 적절한 케이스 핸들링이 필요합니다.

function add(x, y) {
	if( typeof x !== 'number' || typeof y !== 'number') {
    	throw new TypeError("함수의 인자는 숫자 값이어야 합니다.")
    }
    
    return x + y;
}

add('a', 'b') //TypeError

 

 

3. 매개변수에 기본값을 할당할 수 있습니다.

3개의 숫자를 받아 더해서 반환하는 함수가 있다고 생각해봅시다. 2개를 입력할 경우, 3번째 인수값이  undefined이기 때문에 NaN의 결과가 출력되겠죠? 그럴 때 매개변수에 기본값을 설정해줌으로써 더한 값이 반환되게 설정할 수 있습니다. 전달받은 매개변수의 값이 없을 경우 || 단축 평가를 이용해 0을 할당해주거나,  매개변수 목록을 작성하는 곳에서 (a = 0, b = 0, c = 0) 의 형식으로 기본값을 설정해줄 수 있습니다. 

function add(a, b, c) {
  a = a || 0;
  b = b || 0;
  c = c || 0;

  return a + b + c;
}

add(3) // 3
add(2, 2) // 4
add() // 0


function add2(a = 0 , b = 0, c = 0) {
  return a + b + c;
}

 

 

 

4. 매개변수의 최대 변수는 명시적으로 제한하고 있지 않다.

자바스크립트에서 매개변수의 최대 변수는 제한되어 있지 않습니다. 다만 너무 많은 매개변수를 전달하도록 구현을 하게되면, 함수를 봤을 때 사용법을 이해하기도 어렵고, 의도치 않은 실수를 발생시킬 가능성도 높입니다.  

함수를 생성할 때에는 한가지 작업만 하도록 하고, 가장 작은 단위의 기능만 처리하도록 하는게 좋습니다. 최대 3개 이상의 매개변수를 전달받지 않도록 하는것을 권장합니다.  만약 그 이당의 매개변수가 필요할 경우 하나의 매개변수를 선언하고, 객체를 인수로 전달하도록 하는 것도 유용하게 사용할 수 있습니다. 

다만 객체는 레퍼런스 주소를 전달하기 때문에 사용하고자 하는 의도에 맞게 주의해 사용할 필요가 있습니다.

 

 

 

5. 함수 내부의 반환문은 두가지 역할을 한다.

함수에서 return 키워드로 실행 결과를 외부로 반환할 수 있습니다. 반환문은 두가지 역할을 합니다. 

첫번째로는 함수의 실행을 중단시킬 수 있고, 두번째로는 return뒤에 오는 값, 표현식을 평가해 반환할 수 있습니다. 만약 return 키위드가 없는 함수는 어떻게 될까요? 없는 경우 undefined가 반환되며 함수가 종료됩니다.

 

 

 

6. 함수에 나머지 매개변수를 정의할 수 있습니다.

함수에 정해지지 않은 나머지 매개변수를 정의할 수 있습니다. arguments 객체와의 차이는 arguments 객체는 전달되는 모든 전달 인자를 포함하는 반면, 나머지 매개변수는 정해지지 않은 나머지를 의미합니다. 그리고 배열로 사용할 수 있습니다.

function add(x, ...restNum) {
	console.log(restNum) // [10, 15]
	for (let i=0; i < restNum.length; i++){
  		x += restNum[i];
	}
    return x;
}

add(5, 10, 15) // 30

위의 코드의 경우  restNum에는 [10, 15]가 할당됩니다. 함수가 호출될 때 전달된 인수 목록에서 순차적으로 5 =  x에 대입되고, 나머지 목록들은   ...나머지에 배열로 할당됩니다. 배열이기 때문에 배열에서 사용되는 indexOf와 같은 메소드를 사용 가능합니다.

 

 

 


 

 

글을 작성하는 현재는 2021년 12월 31일입니다. :) 행복한 한해 되셨나요? 

전 이래저래 공부한다고 바쁘게 살아온 한해였어요. 제 공부에 급급해서 가족들과 사랑하는 사람들과의 시간에 소홀했던 한해였네요. 

오늘이 가기전에 가족들에게 감사했다고 전화해야겠어요.

 

얼마 전 인수로 전달한 객체의 원본데이터가 변해서 한참 원인을 찾았던 기억이 납니다. 

매개변수와 인수가 메모리에 어떻게 저장이 되는지, 함수가 실행되고 종료될 때를 구체적인 예와 함께 들으니 이해가 더 잘되었습니다. :) 

스터디를 진행하며 블로그 글들이 쌓이고, 지식도 정리되는 기분이라 참 좋습니다.

 

2022년 새해 복 많이 받으세요! 

그리고 즐거운 코딩라이프되세요~! 

 

 

JavaScript 스터디 팀 러버덕과 함께 합니다.