Javascript/vanilla

자바스크립트 내장함수

브라더 코드 2021. 8. 14. 14:46

자바스크립트를 사용하면서 내장함수를 아는 것은 중요하다.

for문과 if문으로만 코드를 짜려다보면 잘 안될때가 있고 효율이 떨어지는 경우가 있다.

기본 내장함수 중에 map, filter 에 대해 정리해보고자 한다

 

1. map

map 함수는 배열 내의 요소를 순회하면서 주어진 함수를 호출하고 새로운 배열을 생성한다.

 

배열.map((요소) => {return 요소})

// map을 실행하여 각 요소에 2배를 곱한 값으로 새로운 배열 생성
const a = [1,3,5,6];
const b = a.map((i) => {return i * 2});
console.log(b); // [2,6,10,12]

 

포인트는 기존 배열을 수정하지 않고 새로운 배열을 만든다는 것이다. 위의 예에서 a와 b는 다른 객체(배열)이고 a의 값은 변하지 않는다.

 

여기서 잠깐! forEach와는 어떻게 다른걸까? 아래 예시를 보자.

 

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

// map
let b = a.map((i) => {
    return i * 10;
})
console.log(b); // [10, 20, 30, 40, 50]

// forEach
a.forEach((v,i) => {
    return a[i] = v * 6;
})
console.log(a); // [6, 12, 18, 24, 30]

 

그렇다. forEach는 새로운 배열을 반환하지 않는다. 그래서 현재 배열을 변경하는데 사용된다. 

 

map의 장점은 배열의 요소명이 규칙적이지 않을때 나타난다.

id가 101~107인 div요소들이 있다고 하자. 서버요청을 하기 위해 모든 div요소들의 값을 가져와야 할 때 제이쿼리를 사용할때가 있다. 제이쿼리를 사용하면 다음과 같은 코드를 쓴다.

 

let a = [];
for (let i=1; i<8; i++) {    
    a.push($("#10"+i).val());    
}

 

for문으로 div 요소에 접근해서 값을 가져올 수 있다. 그런데 여기서 id가 규칙적이지 않고 중간에 103 대신 103_a, 103_b가 있다고 하자. 그럼 for문으로 접근하기 어려울 것이다. 이때 map을 사용하면 된다.

 

let arr = ['101','102','103_a','103_b','104','105','106','107'];
let a = [];
arr.map((i) => {
    a.push($('#'+i).val());
})

 

미리 101부터 107까지(103_a, 103_b 포함)의 문자열 배열을 만들어 놓는다. 그리고 그 배열을 맵 돌려서 div요소에 접근, 값을 가져온다.

(그런데 위 예시에서는 map 대신 forEach를 써도 된다. 왜냐하면 map으로 새로운 배열을 만드는 로직이 아니기 때문이다. map이 좋아서 썼다^^; 어차피 return을 하지 않기 때문에 메모리에 값이 저장되지 않아 괜찮다고 생각한다)

 

2. filter

filter 함수는 배열 내의 요소를 순회하면서 주어진 조건문을 만족하는 요소만 반환하여 새로운 배열을 생성한다. 

 

배열.filter((요소) => {return 조건문})

// 주어진 배열에서 50보다 작은 요소를 filter
const a = [1,3,19,49,50,101,2000];
const b = a.filter((i)=>{return i<50})
console.log(b); // [1,3,19,49]

 

뜯어보면 조건문의 리턴값은 boolean을 가진다. 그러니까 리턴값이 true인 요소만 모아서 새로운 배열을 만드는 것이다. 그런데 만약 만족하는 요소가 없다면 어떻게 될까?

 

// 주어진 배열에서 2000보다 큰 요소를 filter
const a = [1,3,19,49,50,101,2000];
const b = a.filter((i)=>{return i>2000})
console.log(b); // []

 

그렇다. 빈 배열을 반환한다. undefined가 아닌 빈 배열을 반환하는 것을 기억해야 한다. 보통 Array 메소드를 여러개 연결하여 사용하는데 filter를 할때 빈 배열을 반환함으로써 중간에 오류가 나지 않는다. 그리고 다음 메소드를 사용할 수 있다. 예제를 보자.

 

// 4의 배수만 구해서 각 요소를 3배
const a = [100, 150, 234, 947, 20, 988, 4001];
const b = a.filter((i) => {
    return i % 4 == 0;
}).map((i) => {
    return i * 3;
});
console.log(b); // [300, 60, 2964]

 

위 예시는 filter와 map을 연결해서 쓴 것이고 문제없이 값이 나온다. 그런데 filter의 결과가 없는 경우도 있다. 아래 예제를 보자.

 

// 4의 배수만 구해서 각 요소를 3배
const a = [101, 150, 234, 947, 23, 987, 4001]; // 4의 배수가 없음
const b = a.filter((i) => {
    return i % 4 == 0;
}).map((i) => { // filter를 한 결과 빈 배열이 반환됨
    return i * 3;
});
console.log(b); // [] <-- map의 콜백함수는 한번도 호출되지 않았으나 에러가 나지 않음

 

4의 배수가 없어서 빈 배열을 반환했고 그것으로 map을 돌렸다. 그래서 결과는 빈 배열이 나왔다.

만약 filter의 결과값이 빈 배열이 아닌 undefined가 나왔다면 에러가 발생했을 것이다(NaN).

 

 

* map과 filter의 공통점은 기존 배열은 건드리지 않으면서 새로운 배열을 리턴한다는 것이고, 차이점은 map은 콜백함수가 적용된 새 요소를, filter는 조건문을 만족하는 요소를 반환한다는 점이다.

 

 

 

 

 

 

잠깐 퀴즈~!!

두 배열에 교집합을 구하는 코드는?

const arr1 = ['1','2','3','4','5'];

const arr2 = ['1','2'];