탱구탱구 개발자 일기

반복 메서드

배열의 모든 요소를 순회하며 특정한 작업을 수행하거나 특정 조건을 만족하는 요소를 가져올 때 사용한다. 반복 메서드 대부분은 첫 번째 인수로 함수의 참조를 받는 고차 함수이다.

 

※고차 함수

고차 함수는 하나 이상의 함수를 인수로 취하거나 함수를 결과로 반환하는 함수를 말한다.

고차 함수는 인자로 받은 함수를 필요한 시점에 호출하거나 클로저를 생성하여 반환한다.

 고차 함수 예시

let f = function(v) {
    return v + 5;
};

let f2 = function(f, v) {
    return f(f(v));
};

console.log(f2(f, 5)); // 15

 

특징

  • 반복 메서드의 인수로 전달한 함수는 배열의 요소마다 호출된다.(희소 배열이면 없는 요소에 대해선 호출 안함)
  • 첫 번째 인수인 함수에 전달되는 세 개의 인수가 있다. 보통 첫 번째 인수만 사용한다.
    • 첫 번째 인수(value) : 현재 처리하고 있는 배열 요소의 값
    • 두 번째 인수(index, 생략 가능) : 현재 처리하고 있는 배열 요소의 인덱스
    • 세 번째 인수(array, 생략 가능) : 메서드가 적용되는 배열의 참조
  • reduce와 reduceRight를 제외한 나머지 반복 메서드에는 두 번째 인수를 지정할 수 있다. 이 때 그 두 번째 인수는 첫 번째 인수로 받은 함수 안의 this 값이며 생략 가능하다.

종류

  • forEach
  • map
  • reduce

forEach 메서드

인수로 받은 함수를 배열의 요소별로 한 번씩 실행한다. 첫 번째 인수로 들어가는 함수에는 위에서 말한 인수 세 개가 전달된다. 기존 반복문인 for문 대신 많이 쓰인다.

 

예제 1. 배열 요소들의 합

let a = [1, 2, 3, 4, 5];
let sum = 0;
a.forEach((v) => {
    sum += v;
});
console.log('sum:', sum);

결과

sum: 15

 

예제 2. 각 배열 요소의 제곱 값으로 배열 수정 

a.forEach((v, i) => {
    a[i] = v * v;
});
console.log(`a:`, a);

결과

a: (5) [1, 4, 9, 16, 25]

 

map 메서드

인수로 받은 함수를 배열의 요소별로 한 번씩 실행하며, 마지막에는 그 함수가 반환한 값으로 새로운 배열을 생성한다. map 메서드의 인수로 넘기는 함수는 반드시 값을 반환해야 한다.(return 문이 필수)

forEach 메서드에서 제곱값으로 배열을 만드는 예제를 map 메서드로 바꾸면 아래와 같다.

 

예제 1. 배열 요소의 제곱값으로 배열 생성

let a = [1, 2, 3, 4, 5];
let b = a.map(v => {
    return v * v;
});

b;

결과

(5) [1, 4, 9, 16, 25]

 

예제 2. 배열 요소의 요소별 제곱근으로 배열 생성

 

// 배열 요소의 요소별 제곱근으로 배열 생성
let x = [1, 4, 9, 16, 25];
let y = x.map(Math.sqrt);
y;

결과

(5) [1, 2, 3, 4, 5]

JavaScript 내장 함수를 바로 사용할 수 있다.

 

예제 3. 객체 배열의 요소를 순회하여 각 객체가 가진 특정 프로퍼티 값으로 배열을 생성

 

let people = [
    {name: "준영", age: 30},
    {name: "영구", age: 30},
    {name: "뇌병", age: 30},
    {name: "경북", age: 30},
    {name: "염탁", age: 30}
];


let names = people.map(person => person.name);
let ages = people.map(person => person.age);

console.log('names:', names);
console.log('ages:', ages);

 

결과

names: (5) ["준영", "영구", "뇌병", "경북", "염탁"]
ages: (5) [30, 30, 30, 30, 30]

map 메서드의 반환값원본 배열과 같은 개수의 원소가 들어 있는 배열이다. 따라서 map 메서드의 반환 값에 Array.prototype의 메서드를 메서드 체인으로 연결해서 배열 처리가 가능하다.

 

예제 4. 순회한 객체 배열의 특정 프로퍼티로 배열을 만든 후, 그 배열 요소의 문자열 길이를 반환하는 배열을 생성

 

let people = [
    {name: "준영", age: 30},
    {name: "영구짱", age: 30},
    {name: "뇌병", age: 30},
    {name: "경북", age: 30},
    {name: "염탁짱", age: 30}
];

people
    .map(person => person.name)
    .map(name => name.length);

 결과

(5) [2, 3, 2, 2, 3]

 

reduce 메서드

배열의 첫 번째 요소부터 마지막 요소까지 합성 곱(convolution) 처리를 한다. 그리고 마지막 요소를 처리한 함수가 값을 반환한다.

※ 합성 곱 처리

배열 요소 하나를 함수로 처리한 후에 그 반환값을 다음 번 요소를 처리할 때 함수의 입력 값으로 사용하는 처리 방법

 

기본 형태

array.reduce(callback, initial);

function callback(prev, value, index, array) {}

 

reduce 메서드의 인수

  • callback : 합성 곱을 하는 함수
  • initial : callback이 처음 호출되었을 때의 첫 번째 인수(prev)의 값 => 생략 가능

callback 함수의 인수

  • prev : 이전 배열 요소를 처리한 함수의 반환값 또는 initial 또는 첫 번째 요소의 값
  • value : 현재 처리하는 배열 요소의 값
  • index : 현재 처리하는 배열 요소의 인덱스
  • array : 메서드를 적용 중인 배열의 참조

initial의 지정 여부에 따라 pre, value, index 값의 변동

  • 지정
    • prev : initial 값
    • value : 배열의 첫 번째 요소
    • index : 0
  • 지정X
    • prev : 배열의 첫 번째 요소의 값
    • value : 배열의 두 번재 요소의 값
    • index : 1

예제 1. 배열 요소의 합

 - forEach 사용

let a = [1, 2, 3, 4, 5];
let sum = 0;
a.forEach((v) => {
    sum += v;
});
console.log('sum:', sum);

 - reduce 사용

let a = [1, 2, 3, 4, 5];

// initial 지정
a.reduce((prev, value) => {
    return prev + value
}, 0);

// initial 지정 x
a.reduce((prev, value) => {
    return prev + value
});

 결과

15

위 예제의 경우 initial 인자를 지정한 것과 지정하지 않은 것 둘 다 결과는 동일하다. 그러나 initial을 지정했을 때는 최초 순회 시 prev 값이 initial이기 때문에 연산 과정이 한 번 더 추가된다.

reduce 메서드를 통해 합성 곱 처리를 한다면 배열 요소의 곱이나 대소 비교 등을 비교적 간단하게 처리할 수 있다.

 

예제 2. 배열 요소의 곱

let a = [1, 2, 3, 4, 5];
a.reduce((prev, value) => {
    return prev * value;
});

결과

120

 

예제 3. 배열 요소의 최댓값

a.reduce((p, v) => {
    return (p > v) ? p : v;
});

결과

5

 

예제 4. 배열 요소 연결

let aa = ["A", "B", "C"];
aa.reduce((p, v) => {
    return p + " " + v;
});

결과

"A B C"

사실 이렇게 쓰는 것보다 join 메서드를 사용하는 것이 더 간단하다.

aa.join(" ");

 

예제 5. 문자열 배열의 요소별 길이를 반환하는 객체

let bb = ["saint", "nun", "tang-goo"];
bb.reduce((p, v) => {
    p[v] = v.length;
    return p;
}, {});

결과

{saint: 5, nun: 3, tang-goo: 8}

이 글을 공유합시다

facebook twitter kakaoTalk kakaostory naver band
loading