숫자로 이뤄진 배열의 모든 요소의 합을 출력하는 함수를 만들어라
예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
메소드가 중요한 것이 아니기 떄문에 바로 다음 문제로 넘어가겠습니다.
인자로 주어지는 숫자들의 합을 출력하는 함수를 만들어라
예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 |
당연히 입력값(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
다음 문제로 넘어가겠습니다.
동일한 문제를 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가지 방법을 생각해 봤습니다.
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
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
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
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
arguments
객체는 따로 선언하지 않아도 함수 내부에서 언제든 사용할 수 있습니다.
그러나 선언도 안한 값을 사용하는 것은 이를 모르는 사람이 봤을 때 혼란을 줄 수 있으므로 사용을 지양해야 합니다. 또한 arguments
는 유사배열이라 배열의 메소드들을 사용하기 위해서는 일련의 과정이 필요합니다.
반면 rest parameter는 유사배열이 아닌 배열이기 때문에 사용이 편하나 syntax를 알아야 합니다.
유사배열(array-like)이 무엇이며 이들에서 배열의 내장 메소드를 사용하는 방법은 중요합니다.
예시 중 4번 방법이 가장 직관적이나 나머지 방법들도 매우 중요한 개념을 내포하고 있기 때문에 꼭 숙지하시기 바랍니다.