[JAVASCRIPT] Rest parameter, arguments 객체, 그리고 유사배열(array-like)

포우·2023년 4월 9일
0

Javascript 개념

목록 보기
2/4
post-thumbnail

여기 프로그래머스 코딩테스트 lv.0에 나올법한 문제가 있습니다.

문제1

숫자로 이뤄진 배열의 모든 요소의 합을 출력하는 함수를 만들어라

예1) sum([1, 2])의 반환값은 3
예2) sum([1, 2, 3])의 반환값은 6
예3) sum([1, 2, 3, 4])의 반환값은 10

입력 값츨력 값
[1, 2]3
[1, 2, 3]6
[1, 2, 3, 4]10

어렵지 않죠?

const sum = (arr) => arr.reduce((acc, curr) => acc + curr);

console.log(sum([1, 2])); // 3
console.log(sum([1, 2, 3])); // 6
console.log(sum([1, 2, 3, 4])); // 10

정말 다양한 방법이 존재하지만 저는 Array.prototype.reduce를 사용하여 문제를 풀었습니다.
지금은 reduce메소드가 중요한 것이 아니기 떄문에 바로 다음 문제로 넘어가겠습니다.


문제2

인자로 주어지는 숫자들의 합을 출력하는 함수를 만들어라

예1) sum(1, 2)의 반환값은 3
예2) sum(1, 2, 3)의 반환값은 6
예3) sum(1, 2, 3, 4)의 반환값은 10

입력 값츨력 값
1, 23
1, 2, 36
1, 2, 3, 410

당연히 입력값(argument)이 배열이 아니기 때문에 reduce를 사용할 수 없습니다.
그러면 일단 다수의 인자가 입력이 되었을 때 무엇이 출력되는지 보겠습니다.

const sum = (arg) => arg;

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

인자가 여러개라고 하더라도 함수는 맨처음 인자만을 받습니다.
그러면 나머지 인자들을 어떻게 알 수 있을까요??

여기에서 바로 rest parameter의 개념이 등장합니다.

const sum = (...arg) => arg;

console.log(sum(1, 2)); // [1, 2]
console.log(sum(1, 2, 3)); // [1, 2, 3]
console.log(sum(1, 2, 3, 4)); // [1, 2, 3, 4]

매개변수(parameter) 앞에 ...을 붙였을 뿐인데 모든 인자를 요소로 갖는 배열이 반환되었습니다.
이로써 다수의 인자가 주어졌을 때 함수 내부에서 이들을 활용할 수 있게 되었습니다.
당연하지만 여기에 ...spread operator가 아니라 rest parameter로 서로 다른개념입니다.

배열이 나왔으니 이제 합을 구하는 것은 식은죽 먹기입니다.

const sum = (...arg) => arg.reduce((acc, curr) => acc + curr);

console.log(sum(1, 2)); // 1
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4)); // 10

다음 문제로 넘어가겠습니다.


문제3

동일한 문제를 rest parameter를 사용하지 않고, 함수의 arguments객체를 이용하여 풀어라

argements객체는 선언을 한 적이 없지만 이미 함수 내부에서 접근이 가능한 객체입니다.
해당 객체가 무엇인지 콘솔에 찍어보도로 하겠습니다.

const sum = () => console.log(arguments);
sum();

에러가 발생하네요. arguments가 선언되지 않았다고 합니다.

지금까지 제가 일부러 화살표 함수를 사용했는데요.
arguments객체는 화살표 함수에서 사용 할 수 없습니다.
따라서 다음과 같이 사용해야 합니다.

function sum() {
  return arguments;
}

or

const sum = function() {
  return arguments
}

console.log(sum(1, 2)); // Arguments(2) [1, 2, callee: (...), Symbol(Symbol.iterator): ƒ]
console.log(sum(1, 2, 3)); // Arguments(2) [1, 2, 3, callee: (...), Symbol(Symbol.iterator): ƒ]
console.log(sum(1, 2, 3, 4)); // Arguments(2) [1, 2, 3, 4, callee: (...), Symbol(Symbol.iterator): ƒ]

arguments를 확인해보면 인자들이 배열과 비슷한 형식으로 담겨있습니다.
배열이랑 유사하기 때문에 reduce를 사용 할 수 있나 보도록하죠.

function sum() {
  return arguments.reduce((acc, curr) => acc + curr);
}
console.log(sum(1, 2));
console.log(sum(1, 2, 3));
console.log(sum(1, 2, 3, 4));

당연하게도 배열과 유사하지만 배열이 아니므로 reduce메소드를 사용할 수 없습니다.

이렇게 배열과 유사하지만 배열이 아닌 것을 유사배열이라고합니다.
유사배열의 형식은 다음과 같습니다.

const arrayLike = {
  0: 1,
  1: 2,
  2: 3,
  length: 3,
};

이러한 형식의 데이터는 자바스크립트에서 종종 보이곤 하는데요,
DOM요소를 제어하기 위해 document.querselectorAll로 가져오는 NodeList가 이러한 유사배열입니다.
참고로 NodeList는 유사배열이지만 forEach메소드를 사용할 수 있습니다.


원래 문제로 돌아가 유사배열 arguments를 이용하여 문제를 풀어보도록 하겠습니다.
저는 총 4가지 방법을 생각해 봤습니다.

1. arguments 객체에 reduce 넣어주기

function sum() {
  arguments.reduce = Array.prototype.reduce;
  return arguments.reduce((acc, curr) => acc + curr);
}

console.log(sum(1, 2)); // 3
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4)); // 10

2. Array.prototype.reduce.call

function sum() {
  return Array.prototype.reduce.call(arguments, (acc, curr) => acc + curr);
}

console.log(sum(1, 2)); // 3
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4)); // 10

3. Array.from

function sum() {
  return Array.from(arguments).reduce((acc, curr) => acc + curr);
}

console.log(sum(1, 2)); // 3
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4)); // 10

4. Spread operator로 풀고 [ ]에 담기

function sum() {
  return [...arguments].reduce((acc, curr) => acc + curr);
}

console.log(sum(1, 2)); // 3
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4)); // 10

Wrap Up

  1. arguments객체는 따로 선언하지 않아도 함수 내부에서 언제든 사용할 수 있습니다.
    그러나 선언도 안한 값을 사용하는 것은 이를 모르는 사람이 봤을 때 혼란을 줄 수 있으므로 사용을 지양해야 합니다. 또한 arguments는 유사배열이라 배열의 메소드들을 사용하기 위해서는 일련의 과정이 필요합니다.

  2. 반면 rest parameter는 유사배열이 아닌 배열이기 때문에 사용이 편하나 syntax를 알아야 합니다.

  3. 유사배열(array-like)이 무엇이며 이들에서 배열의 내장 메소드를 사용하는 방법은 중요합니다.
    예시 중 4번 방법이 가장 직관적이나 나머지 방법들도 매우 중요한 개념을 내포하고 있기 때문에 꼭 숙지하시기 바랍니다.

profile
개발바닥

0개의 댓글