본문 바로가기

프로그래밍/JavaScript

JS - 자바스크립트 함수 매개변수에 대한 이해

 

자바스크립트에서 함수 매개변수는 다른 언어의 매개변수와는 조금 다르게 동작한다.

 

자바스크립트에서 함수는 매개변수의 숫자를 따지지도않고, 데이터 타입도 체크하지 않는다.

그렇기때문에 매개변수를 두 개 받도록 함수를 만들어도, 꼭 두개를 넘겨야 하는건 아니다.

한개를 전달하거나, 세개를 전달, 그리고 아예 전달하지 않아도, 이를 에러로 간주하지는 않는다.

 

이렇게 되는 이유는 자바스크립트에서 함수 매개변수는, 내부적으로 배열로 표현되기 때문이다.

이 배열은 "항상" 함수에 전달되지만, 어떤 값이 들어있는지 체크하지않는다. 빈 배열이 들어와도 상관없고, 필요한 매개변수보다 더 많은 값이 들어와도 딱히 상관이 없다.

 

자바스크립트에서 함수는 기본적으로 arguments라는 객체를 하나 가지고 있는데, 이 객체를 통해서도 우리가 매개변수로 넣어준 값에 접근할 수 있다.

 

이 arguments 객체는 특이한게 배열처럼 동작하기는 하나, Array의 인스턴스는 아니다.

 

function Hello() {
  console.log("Hello" + arguments[0]);
}

이 코드의 Hello 함수에는 이름 붙은 매개변수가 없다. 하지만 이와는 상관없이 의도대로 동작한다.

우리는 보통 매개변수에 이름을 붙여서 넣지만, 꼭 필요한 건 아니다. 이게 자바스크립트 함수의 중요한 특징이다.

다른 언어와 다르게, 자바스크립트에서는 매개변수에 이름을 붙인다고해서, 함수 시그너처를 만들고 나중에 검사하지 않는다. 즉, 이름붙은 매개변수의 유효성 검사를 하지 않는다.

 

* 시그너처 : 함수에 전달된 매개변수의 개수와 타입을 나타내는 것

 

그리고 arguments 객체를 통해, 함수에 전달된 매개변수의 개수도 알아 볼 수 있다.

function howManyArgs() {
  console.log(arguments.lenght);
}

howManyArgs("string", 12); // 2
howManyArgs(); // 0
howManyArgs(14); // 1

결과는 각각 2, 0, 1 이 된다.

 

이런 방법을 통해서 함수가 받는 매개변수 숫자에 제한을 두지 않고 넘겨받은 매개변수 개수에 맞게 반응 할 수 있다.

function doAdd() {
  if(arguments.length === 1){
    console.log(arguments[0] + 10);
  } else if(arguments.length === 2) {
    console.log(arguments[0] + arguments[1]);
  }
}

doAdd(10) // 20
doAdd(10,20) // 30

매개변수가 한개일때는, 전달받은 매개변수에 10을 더하고, 매개변수가 두개일때는 전달받은 매개변수 두 개를 더한다.

 

그리고, 이름붙은 매개변수와 같이 쓸 수 있는 특징도 가지고있다.

 

function doAdd(num1, num2){
  if(arguments.length === 1){
    console.log(num1 + 10);
  } else if(arguments.length === 2) {
    console.log(arguments[0] + num2);
  }
}

 

그리고 arguments 객체의 흥미로운 점은 arguments 객체의 프로퍼티 값을 이에 대응하는 이름 붙은 매개변수에서 자동으로 반영한다는 점이다.

 

function doAdd(num1, num2) {
  arguments[1] = 10;
  console.log(arguments[0] + num2);
}

이 doAdd 함수는 두번째 매개변수 값을 항상 10으로 바꿔서 처리할 것이다.

 

이름 붙은 매개변수는 arguments 객체의 프로퍼티를 자동으로 반영하므로 arguments[1]의 값을 바꾸면 num2도 바뀌고, 둘 모두 10이 된다. (함수에서)

 

둘이 같은 메모리공간을 사용하는건 아니지만, 값은 반영된다. 이 때 동기화 되는것은 아니고, 단반양 반영이다.

즉, 이름붙은 매개변수값을 바꿔도, arguments 프로퍼티는 바뀌지않는다.

 

또 위의 doAdd 함수에서 매개변수를 하나만 넘기면 arguments 값을 바꾸더라도 이름붙은 매개변수에는 아무 영향이 없다! 왜냐하면, arguments 객체의 length 프로퍼티가 함수 정의에서 정의한 매개변수 숫자를 따르지 않고, 함수를 호출할 때 넘긴 이름 붙은 매개변수 목록을 따르기 때문이다.

 

그리고 arguments 객체는 다른값으로 덮어 씌울 수 없다. 덮어씌우려고 하면 오류가 발생한다.

 

그리고 방금 위에서 말한 arguments 값을 바꾸더라도 이름붙은 매개변수에는 아무 영향이 없다는 말은 다음과 같은 의미이다.

 

function doAdd(num1, num2) {
  arguments[1] = 10;
  console.log(num1, num2);
  console.log(arguments);
}

doAdd(10);
// 10, undefined
// [10]

doAdd(20, 30);
// 20, 30
// [20, 10]

 

 

* 니콜라스 자카스 저자의 "프론트엔드 개발자를 위한 자바스크립트 프로그래밍" 서적에 나오는 내용을 참고하여 정리한 글입니다. *