본문 바로가기
Programming/자바스크립트

[자바스크립트] 배열 - 메소드2

by 코딩하는 랄로 2023. 10. 28.
728x90

이전에 배열의 기본적인 메소드에 대해 다룬 포스팅이다. 이번 포스팅에서는 유용하게 사용하는 또 다른 배열 메소드에 대해서 추가로 다루겠다.

 

https://codingralro.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%B0%B0%EC%97%B4-%EB%A9%94%EC%86%8C%EB%93%9C

 

[자바스크립트] 배열 - 메소드1

이번 포스팅에서는 배열이 가지고 있는 메소드들 중 많이 사용하는 몇가지 메소드들에 대해서 알아보겠다. 자바스크립트의 배열의 개념에 대해서 먼저 알고싶으신 분들은 아래의 링크를 참고

codingralro.tistory.com

 

 

 

Map()

배열의 map 메소드는 함수를 인수(콜백함수)로 받는데, 각각의 요소에 대해서 해당 함수를 동작시킨 후 나온 결과를 가진 새로운 배열을 반환한다.

 

먼저 예시를 살펴보자. 해당 예시는 배열 요소를 2배로 증가시킨 값들의 배열을 생성하는 예시이다.

// map()
const arr = [1, 2, 3, 4, 5]

// 콜백함수의 인수가 X
let arrDouble = arr.map(function() {return 2; });
console.log(arrDouble); //[2, 2, 2, 2, 2]


// 콜백함수의 인수가 O
arrDouble = arr.map(function(el) {return el * 2; });
console.log(arrDouble); //[2, 4, 6, 8, 10]


// 화살표 함수도 사용 가능
arrDouble = arr.map((el) => el * 2);
console.log(arrDouble); //[2, 4, 6, 8, 10]


// 홀수일때만 반환하면 어떻게 나올까?
arrDouble = arr.map((el) => { if (el % 2) return el * 2 });
console.log(arrDouble); //[2, undefined, 6, undefined, 10]

 

위의 예시를 통해 알수있는 정보는 다음과 같다.

 

  • map의 인수를 통해 전달되는 함수는 무조건 값을 리턴해야 한다. 
  • 콜백 함수(인수로 넘겨준 함수)의 첫번째 인수(el)는 배열의 요소이다.

 

즉, map 메소드는 요소를 인수로 넘겨주든 아니든 무조건 배열 요소의 개수만큼 실행이 되고 콜백함수의 리턴값이 없다면 undefined를 배열에 집어넣은다. 그렇기 때문에 기존의 배열(map 메소드를 호출한)과 반환되는 새로운 배열의 크기는 항상 일치한다. ( N : N 관계)

 

map 메소드는 콜백함수에게 배열의 요소 이외에도 여러 인수를 넘겨줄 수 있다.

// map(callback(element, index, array) {}, this)
// element는 요소
// index는 해당 요소의 index값
// array는 map 메소드를 호출한 array
// callback함수에서 사용할 this를 넘겨줌

// 서로 반대편에 있는 배열의 요소와 더하기
// ex) [1, 2, 3] => [1+3, 2+2, 3+1]

const arr = [1, 3, 10, 2]
const rst = arr.map((el, index, arr) => return el + arr[arr.length-index-1])
console.log(rst); //[3, 13, 13, 3]

 

 

 

Reduce()

reduce 메소드는 호출의 결과로 무조건 1개의 결과값을 반환한다.(N : 1관계) reduce의 구문은 다음과 같다.

reduce(callback (accumulator, currentValue, index, array){return}, initialValue)

 

해당 인수에 대한 설명은 아래와 같다.

  • callback : 배열의 요소에 대한 작업을 하는 함수로 무조건 리턴값을 반환해야 한다.
  • accumulator : 누산기, 값이 축적되는 변수로 이전의 콜백의 결과가 저장된다. 
  • currentValue : 배열의 요소
  • index : 해당 요소의 인덱스값
  • array : reduce 메소드를 호출한 배열
  • initailValue : accumulator의 초기값을 설정, 없을 경우 accumulator의 초기값은 배열의 첫번째 요소로 지정되고 배열의 2번째 요소부터 callback 함수를 실행한다.

 

다음은 배열의 합을 reduce를 사용하여 구하는 기본적인 예제이다. 

// reduce(callback (accumulator, currentValue, index, array){return}, initialValue)
// N : 1
// 배열의 합 구하기
let arr = [1, 2, 3, 4, 5]

// 초기값X
let sum = arr.reduce((acc, cur) => acc + cur);
// 콜백함수가 몇번 호출되었을까? => 4번
// 1 + 2 => 3
// 3 + 3 => 6
// 6 + 4 => 10
// 10 + 5 => 15
console.log(sum); //15


// 초기값O
let sum = arr.reduce((acc, cur) => acc + cur, 0);
// 콜백함수가 몇번 호출되었을까? => 5번
// 0 + 1 => 1
// 1 + 2 => 3
// 3 + 3 => 6
// 6 + 4 => 10
// 10 + 5 => 15
console.log(sum); //15

 

reduce는 다른 메소드에 비해 개념이 어렵고 복잡하기 때문에 초기에 잘 이해하기 위해서는 reduce 함수가 어떤 과정(흐름)을 거치면서 진행되는 지를 살펴보는 것이 중요하다. reduce 메소드를 잘 활용하게 된다면, 위의 map 메소드를 포함한 다른 메소드들도 reduce로 할 수 있게 된다.

// reduce로 map 따라하기
const arr = [1, 2, 3, 4, 5]

let arrMap = arr.map((el) => el * 2);
console.log(arrMap); //[2, 4, 6, 8, 10]

let arrReduce = arr.reduce((acc, cur) => {
                               acc.push(cur * 2);
                               return acc;
                           }, []); //초기값을 빈 배열로 지정

console.log(arrMap); //[2, 4, 6, 8, 10]

 

초기값을 빈 배열로 지정하여, 콜백함수를 돌면서 2배 한 값은 배열에 집어넣은 후 다시 해당 배열을 넘겨주는 흐름의 코드이다.

 

 

 

forEach()

forEach는 for 반복문과 똑같이 동작하는 메소드라고 생각하면 된다. forEach의 콜백함수는 반환값을 갖지 않기 때문에 해당 배열을 돌면서 특정 동작을 수행하는데에 사용되는 코드이다.

// forEach(callback(element, index, array) {}, this );
// 반환값 X
// 배열의 각 요소를 출력
let arr = [1, 2, 3, 4, 5];
arr.forEach((el) => console.log(el)); // 1 2 3 4 5

 

위의 예시처럼, forEach는 사실상 for문의 기능을 한다. 하지만 forEach는 break문으로 중단할 수 있는 for문과는 달리 forEach는 return을 통해 중단할 수 없다. 그렇기 때문에 일반적으로 for문에 비해 forEach의 실행 속도는 느린편이다. 

 

그렇다면 forEach를 사용하는 이유가 무엇일까? 바로 메소드 체이닝이 가능하기 때문인데, 메소드 체이닝은 간단하게 메소드를 이어붙여서 사용하는 것을 말한다. forEach 문은 배열의 메소드이기 때문에 이전 메소드가 배열을 반환한다면 이어붙여서 바로 사용할 수 있는 것이다.

// 아래예제 간단한 작업이기때문에 하나의 for문으로 가능하지만...
// foEach 사용 이유에 대한 이해를 위해...

// for문
const arr = [1, 2, 3, 4, 5]

//2배
const arr1 = [];
for(let x of arr) { arr1.push(x * 2) }

// 출력하기
for(let x of arr1) { console.log(x) }


// forEach
arr.map(x => x * 2 ).forEach(x => console.log(x));

 

메소드 체이닝을 통해 for문을 사용할 때 처럼, 변수의 선언도 줄일 수 있고 코드도 간결해진다. 하지만 앞서 말했듯이, forEach는 중간에 탈출할 수 없기 때문에 남용할 경우, 실행시간이 길어진다는 단점 또한 존재한다.

 

 

 

filter()

filter 메소드는 이름 그대로 특정 조건에 맞는 배열의 요소를 걸러내어 새로운 배열로 만들어 반환해주는 메소드이다. 그렇기 때문에 콜백함수의 리턴값은 해당 요소가 조건을 만족하는지에 대한 불린값이 되어야 한다.

// filter(callback(element, index, array) {return true/false }, this)
// N : M 관계 , M <= N
const arr = [1, 2, 3, 4, 5];

const arr1 = arr.filter(el => el % 2 );
console.log(arr1); //[1, 3, 5]

 

 

 

find()

find() 메소드는 조건에 맞는 모든 요소를 새로운 배열로 반환해주는 filter와는 달리, 해당 조건에 맞는 요소 중 첫번째 값만을 리턴한다. 만약 만족하는 값이 없으면 undefined를 리턴한다.

 

그렇기 때문에 모든 요소에 대한 검사를 진행해야 하는 filter와는 달리, find 메소드는 조건을 만족하는 요소를 찾는 즉시 값을 반환하고 메소드를 종료하게 된다.

// find(callback(element, index, array), this)
// 찾는 즉시 해당 요소 반환 후 종료
// 없으면 undefined 반환
const arr = [1, 2, 3, 4, 5]

let rst = arr.find((el) => el > 3));
console.log(rst) //4

let rst = arr.find((el) => el > 5));
console.log(rst) //undefined

 

 

 

some() / every()

some()은 배열의 요소 중 하나라도 해당 조건을 만족하는 요소가 있는지를 확인하는 메소드이고, 반대로 every는 모든 요소가 해당 조건을 만족하는지 확인하는 메소드이다.

 

some 메소드는 하나라도 만족하면 되기 때문에 만족되는 종료되고 every 메소드는 모든 요소가 만족을 해야 하기 때문에 하나라도 만족하지 않을 경우 종료된다.

// some(callback(element, index, array), this)
// 하나라도 만족하면 true 리턴 => 종료
// callback 호출횟수 : 1 ~ N
const arr = [1, 2, 3, 4, 5]

// 3보다 큰 수가 하나라도 존재하나?
let rst = arr.some(el => el > 3);
console.log(rst); //true


// some(callback(element, index, array), this)
// 하나라도 만족하면 true 리턴 => 종료
// callback 호출횟수 : 1 ~ N

// 모두 3보다 큰 수 인가?
rst = arr.every(el => el > 3);
console.log(rst); //false

 

 

 

728x90