-
함수의 인수 (rest와 arguments 객체)개발 2020. 4. 14. 23:49
자바스크립트에서는 함수를 호출할 때 인수를 생략할 수 있습니다. 반대로 함수의 매개변수에 작성된 인자 개수보다 더 많은 개수의 인수를 넘겨서 함수를 실행할 수 있습니다.
첫번 째 방법으로는 arguments객체이고, 두번 째 방법으로는 rest 파라미터(spread operator) 가 있습니다.
1. arguments 객체
arguments 객체는 매개변수 개수가 정확하게 정해지지 않은 함수를 구현하거나, 전달된 인자의 개수에 따라 서로 다른 처리를 해줘야 하는 함수에 유용하게 사용할 수 있습니다. 또한 매개 변수가 명시적으로 선언되지 않은 경우에도 사용할 수 있습니다.
모든 함수에서 사용할 수 있는 지역 변수로 argument 변수가 있고, arguments변수의 값은 Arguments 객체입니다.
함수를 호출할 때 매개변수로 전달되는 인자 값과 this, 그리고 arguments 객체가 암묵적으로 함수 내부로 전달됩니다.
함수안에서 arguments를 콘솔에 찍어보고 정말로 arguments라는 변수에 Arguments라는 객체 값이 담겨있는지 확인해보겠습니다.
Arguments 객체를 열어보면 안에 length 속성이 있는 것을 볼 수 있습니다.
length 속성이 있는것으로 보면 arguments는 배열일 것이라고 생각할 수 있는데, arguments는 객체이지 배열이 아닙니다.
즉, arguments는 유사배열객체 이고, length 프로퍼티가 있으므로 배열과 유사하게 동작하긴 하지만 배열은 아니므로 배열 메서드를 사용할 경우 에러가 발생합니다.
물론 유사 배열 객체에서 배열 메서드를 사용하는 방법은 있으나, 이 컨텐츠에서는 다루지 않겠습니다.
위의 사진에서 처럼 arguments 객체는 다음과 같이 세 부분으로 구성되어 있습니다. (__proto__프로퍼티 제외)
- 함수를 호출할 때 넘겨진 인자 (유사배열 형태) : 함수를 호출할 때 첫 번째 인자는 0번 인덱스, 두 번째 인자는 1번 인덱스...
이렇게 인덱스가 주어지고 해당 인덱스의 값 (전달인자로 넣어준 값)이 유사배열 형태로 들어옵니다. - length 프로퍼티 : 호출할 때 넘겨진 인자의 개수를 의미합니다.
- callee 프로퍼티 : 현재 실행 중인 함수의 참조 값 (위 사진에서는 foo()함수 입니다.)
arguments 객체에 인덱스가 있는것을 보면 이 인덱스값으로 arguments 값에 접근할 수도 있고, 재할당도 가능하다는 것을 알 수 있습니다.
arguments[0] // 1 arguments[0] = 2; // Arguments [2, callee: ƒ, Symbol(Symbol.iterator): ƒ]
다음은 sum이라는 함수를 예제로 호출된 인자 개수에 상관없이 이들 각각의 값을 모두 더해 리턴하는 함수를 살펴보겠습니다.
function sum(){ let result = 0; for(let i = 0; i < arguments.length; i++){ result += arguments[i]; } return result; } sum(1,2,3); // 6 sum(1,2,3,4,5,6,7,8,9); // 45
이 처럼 arguments 객체를 사용할 경우 함수가 호출될 당시의 전달 인자들에 유사배열 형태로 접근할 수 있으므로 이러한 구현이 가능한 것입니다.
하지만, arguments 객체는 유사배열이기 때문에 배열의 메서드를 사용하지 못한다는 단점이 있다고 위에서 언급했습니다.
함수내에서 배열을 가지고 배열 메서드를 사용하는 경우가 많을텐데 그럴 때마다 arguments 객체로 받는다면 배열 메서드를 사용할 수 있게끔 어떠한 작업을 또 해주어야 하는 번거로움이 발생하게 될겁니다.
그러한 문제점을 해결할 수 있는 방법은 rest 파라미터 입니다.
2. rest 파라미터
rest파라미터는 정해지지 않은 전달인자를 배열로 나타낼 수 있게 합니다. arguments와는 다르게 rest파라미터는 유사배열이 아닌 배열입니다. 다음 사진을 통해 rest파라미터가 어떻게 값을 받아오는지 알아보겠습니다.
foo() 함수를 실행하면서 전달인자로 1, 2, 3, 4, 5를 전달해주었고 매개변수로 a, b 를 써주어서 첫번 째와 두번 째 인수만 매핑되어 일반적인 매개변수와 같이 사용됩니다. 3번째로 써준 ...rest 에는 앞에서 매핑된 전달인자를 제외한 그 뒤로 오는 모든 전달인자를 배열로 받아옵니다.
단, rest 파라미터를 맨 첫번 째에 써준 후, 그 뒤에 매핑시킬 변수 값( 위의 사진에서는 a, b )을 넣어주어서는 안됩니다.
rest 파라미터는 매핑하고 난 뒤의 전달인자가 하나만 있을 때에도 배열을 갖고, 전달 받은 값이 없을 때에도 빈 배열을 리턴합니다.
function foo(a, b, ...rest){ console.log(a); console.log(b); console.log(rest); } foo(1, 2, 3); // 1, 2, [3] foo(1, 2); // 1, 2, []
다음은 rest 파라미터로 받아온 인수들에 배열 메서드인 filter를 사용해보고 마무리하도록 하겠습니다.
function foo(a, ...rest){ let result = rest.filter(function(val){ return a <= val; }); return result; } foo(3, 1, 2, 3, 4, 5); // [3, 4, 5]
매개변수 a로 매핑시킨 첫번 째 인수를 제외하고 그 뒤에 오는 모든 인수들을 ...rest 파라미터로 받았고, filter 메서드를 사용하여 a보다 크거나 같은 값들을 필터링하여 배열에 담아 return 한 것입니다.
만약 arguments 처럼 rest도 유사배열객체 였다면 이러한 배열 메서드를 사용할 수 없었을 것입니다.
'개발' 카테고리의 다른 글
함수를 호출할 때의 this 바인딩 (0) 2020.04.19 객체의 메서드를 호출할 때 this 바인딩 (0) 2020.04.16 prototype과 prototype Chain (0) 2020.04.14 생성자와 new (0) 2020.04.12 객체지향 프로그래밍 (0) 2020.04.12 - 함수를 호출할 때 넘겨진 인자 (유사배열 형태) : 함수를 호출할 때 첫 번째 인자는 0번 인덱스, 두 번째 인자는 1번 인덱스...