arguments 객체

arguments 객체는 함수에 전달된 인수에 해당하는 “Array 형태”의 객체이다.
여기서 “Array 형태”란, arguments가 length 속성과 더불어 0부터 인덱스된 다른 속성을 가지고 있지만, Array의 forEach, map과 같은 내장 메서드를 가지고 있지 않다는 뜻이다.

arguments 객체는 모든 함수 내에서 이용 가능한 지역 변수이다(즉, 함수 외부에서는 참조할 수 없다). arguments 객체에는 함수를 호출할 때 입력한 인자가 담겨 있다. arguments 객체를 사용하여 함수 내에서 모든 인수를 참조할 수 있다.

예제를 통해 이해해보자.

1
2
3
4
5
6
7
8
9
10
function add(x,y) {
console.log(arguments);
// [Arguments] { '0': 2, '1': 5, '2': 10 }
console.log(arguments[0]); // 2
console.log(arguments[1]); // 5
console.log(arguments[2]); // 10
return x+y;
}

add(2, 5, 10);

함수 내에서 arguments라는 변수를 선언한 적이 없음에도 불구하고 사용가능한 것을 알 수 있다. 또, arguments는 배열 형태로 인수에 대한 정보를 갖고 있으며 각각의 인수를 참조할 수도 있다.
위 예제를 보면, 매개변수보다 인수가 더 많은 경우 초과된 인수는 버려지지 않고 암묵적으로 arguments 객체의 프로퍼티로 보관된다.

arguments 객체는 함수를 정의할 때, 매개변수 개수를 확정할 수 없는 가변 인자 함수를 구현할 때 유용하게 사용된다.

인수로 전달되는 모든 값을 더하는 함수를 예제로 만들어보자.

1
2
3
4
5
6
7
8
9
function addAll() {
let result = 0;
for( i = 0; i < arguments.length; i++) {
result += arguments[i];
}
console.log(result);
}

addAll(2,5,10);

매개변수의 수

매개변수와 관련된 두가지 수가 있다. 하나는 함수.length, 다른 하나는 arguments.length이다.
arguments.length는 함수로 전달된 실제 인자의 수를 의미하고, 함수.length는 함수에 정의된 인자의 수를 의미한다.

예제를 통해 살펴보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function zero(){
console.log(
'zero.length', zero.length,
'arguments', arguments.length
);
}
function one(arg1){
console.log(
'one.length', one.length,
'arguments', arguments.length
);
}
function two(arg1, arg2){
console.log(
'two.length', two.length,
'arguments', arguments.length
);
}
zero(); // zero.length 0 arguments 0
one('val1', 'val2'); // one.length 1 arguments 2
two('val1'); // two.length 2 arguments 1

정리하면,
함수이름.length : 함수를 정의할 떄 작성한 매개변수(파라미터)의 개수
arguments.length : 함수를 호출할 때 전송되는 인자(arguments)의 개수

arguments를 array로 변환

arguments 객체는 위에서도 설명했듯이, 배열 형태로 인자 정보를 담고 있지만 실제 배열이 아닌 유사 배열 객체(array-like object)이다.
유사 배열 객체란 length 프로퍼티를 가진 객체로 for문으로 순회할 수 있는 객체를 말한다.

이터러블의 개념이 없었던 ES5에서 arguments 객체는 유사 배열 객체로 구분되었다. 하지만 이터러블이 도입된 ES6부터 arguments 객체는 유사 배열 객체이면서 동시에 이터러블이다.

유사 배열 객체는 배열이 아니므로 배열 메서드를 사용햘 경우 에러가 발생한다. 따라서 배열 메서드를 사용하려면 Function.prototype.call, Function.prototype.apply 를 사용해 간접 호출해야 하는 번거로움이 있다.

1
2
3
4
5
6
7
8
9
10
function sum() {
// arguments 객체를 배열로 변환
const array = Array.prototype.slice.call(arguments);
return array.reduce(function (pre, cur) {
return pre + cur;
}, 0);
}

console.log(sum(1,2)); // 3
console.log(sum(1,2,3,4,5)); // 15

이러한 번거로움을 해결하기 위해 ES6에서는 Rest 파라미터를 도입했다.

1
2
3
4
5
6
7
// ES6 Rest parameter
function sum(...args) {
return args.reduce((pre, cur) => pre + cur, 0);
}

console.log(sum(1,2)); // 3
console.log(sum(1,2,3,4,5)); // 15

ES6 Rest 파라미터의 도입으로 모던 자바스크립트에서는 arguments 객체의 중요성이 이전 같지는 않지만 언제나 ES6만 사용하지는 않을 수 있기 때문에 알아둘 필요가 있다.