JavaScript_함수다루기(4)

cindycho_0423·2023년 9월 4일
0

Arguments 다루는 법

함수를 호출할 때 파라미터로 전달하는 값

function printArguments(a, b, c) {
  console.log(a);
  console.log(b);
  console.log(c);
}

printArguments('Young', 'Mark', 'Koby');

전달되는 아규먼트의 패턴이 다양할 때 아규먼트가 한 개가 전달되면 한 개만 출력하고, 네 개가 전달되면 네 개 모두를 출력하도록 아규먼트 개수에 따라 유연하게 동작하는 함수를 만들려면 어떻게 해야할까?

자바스크립트에서 함수를 선언할 때 함수 내부에서는 arguments라는 특별한 객체를 사용할 수가 있다. arguments 객체는 배열과 비슷한 모양을 하고 있긴 하지만 모양만 비슷하고 배열의 메소드는 사용할 수 없는 유사 배열이다.

그래도 length 프로퍼티로 아규먼트 개수를 확인할 수도 있고 인덱싱을 통해서 아규먼트 하나하나에 접근을 한다거나 혹은 for...of 문을 통해서 반복 작업도 할 수 있기 때문에 이렇게 arguments 객체를 활용하면 호출할 때 전달되는 아규먼트에 따라 유연하게 동작하는 함수를 만들어낼 수도 있다.

function printArguments(a, b, c) {
  for(const arg of arguments) {
    console.log(arg);
  }
}

arguments라는 객체가 함수 내부에 특정한 기능으로 존재하기 때문에 파라미터의 이름을 arguments로 짓는다거나 함수 내부에서 arguments라는 이름의 변수나 함수를 만드는 것도 피해야 한다.

Rest ParaMeter

arguments 객체에도 몇 가지 아쉬운 점들이 있다.
첫 번째로 arguments 객체가 유사 배열이기 때문에 배열의 메소드는 사용할 수가 없다.
두 번째는 항상 함수를 호출할 때 전달한 이 아규먼트 전체를 다루기 때문에 마지막 두 개만, 혹은 세 개만 따로 묶어서 다루려면 인덱싱을 통해서 한번 더 세분화해야 하는 과정이 필요하다는 점이다.

그런데 ES2015 이후에 이런 arguments 객체의 아쉬움을 해결해주는 Rest Parameter라는 문법이 등장하게 되었다.

function printArguments(...args) {
  for (const arg of args) {
    console.log(arg);
  }
  console.log('----------');
};

printArguments('Young', 'Mark', 'Koby');
printArguments('Captain');
printArguments('Jayden', 'Scott');
printArguments('Suri', 'Jack', 'Joy', 'Noel');

이와 같이 파라미터 하나를 만들어서 그 앞에 마침표 세 개를 붙여준 것이다. 그리고서 arguments 객체 대신 args 파라미터를 사용한건데, arguments 객체를 사용할 때처럼 똑같이 동작하는 것을 확인할 수 있다.

이렇게 일반 파라미터 앞에 마침표 세 개를 붙여준 것을 Rest Parameter 라고 하는데, arguments 객체는 유사 배열이기 때문에 배열의 메소드를 사용할 수 없지만 Rest Parameter는 배열이기 때문에 배열의 메소드를 자유롭게 사용할 수가 있다.

그래서 간단하게 확인해보면 arguments 객체에 메소드를 사용했을 때 Uncaught TypeError가 발생한다.

function printArguments(...args) {
  console.log(args.splice(0, 2)); // ["Young", "Mark"]
  console.log(arguments.splice(0, 2)); // Uncaught TypeError
  console.log('----------');
};

printArguments('Young', 'Mark', 'Koby');
printArguments('Captain');
printArguments('Jayden', 'Scott');
printArguments('Suri', 'Jack', 'Joy', 'Noel');

그리고 Rest Parameter는 일반 파라미터와 함께 사용할 수도 있는데, "Rest(나머지)"라는 이름처럼 앞에 정의된 파라미터에 아규먼트를 먼저 할당하고 나머지 아규먼트를 배열로 묶는 역할을 하기 때문에 일반 파라미터와 함께 사용할 때는 반드시 가장 마지막에 작성되어야 한다.

function printRank(first, second, ...others) {
  console.log('코드잇 레이스 최종 결과'); // 코드잇 레이스 최종 결과
  console.log(`우승: ${first}`); // 우승: Phil
  console.log(`준우승: ${second}`); // 준우승: Won
  for (const arg of others){
    console.log(`참가자: ${arg}`); // 참가자: Emma 참가자: Min 참가자: Luke
  }
}

printRank('Phil', 'Won', 'Emma', 'Min', 'Luke');

항상 전달된 모든 아규먼트를 다루는 arguments 객체와는 다르게 이렇게 명확하게 구분해서 다루어야 하는 부분은 일반 파라미터를 사용하고, 유연하게 다룰 수 있는 부분은 Rest Parameter로 나눠서 필요에 따라 부분적으로 유연하게 활용할 수 있는 것이다.

대부분의 상황에서 Rest Parameter가 가지는 장점이 상대적으로 arguments 객체보다 더 크기 때문에 코드를 작성할 때 가급적이면 Rest Parameter를 우선적으로 활용하고 불가피한 상황에서 arguments 객체를 활용하는게 많은 스타일가이드에서 권장하는 방법이기도 하다. 그러나 상황에 따라 Rest Parameter가 arguments를 100% 완벽하게 대체할 수도 없기 때문에 두 가지 모두 잘 이해하는 것이 좋다.

profile
https://linktr.ee/Hyunji_Cho 🐣

0개의 댓글