공부내용정리/JavaScript

배열 내장함수

코딩하는망아치 2021. 4. 18. 14:25

forEach

forEach 는 가장 쉬운 배열 내장 함수이다. 기존에 우리가 배웠던 for문을 대체 시킬수 있다. 예를들어 다음과 같은 텍스트 배열이 있다고 가정해보자.

const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];

만약 배열안에 있는 모든 원소들을 모두 출력해야 한다면 for문을 사용하여 다음과 같이 구현할수 있다.

const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];

for (let i = 0; i < superheroes.length; i++) {
  console.log(superheroes[i]);
}

배열의 forEach함수를 사용하면 다음과 같이 구현할수 있다.

const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];

superheroes.forEach(hero => {
  console.log(hero);
});

forEach함수의 파라미터로는, 각 원소에 대하여 처리하고 싶은 코드를 함수로 넣어준다. 이 함수의 파라미터 hero는 각 원소를 가르키게 된다.

이렇게 함수형태의 파라미터를 전달하는 것을 콜백함수라고 한다. 함수를 등록해주면, forEach가 실행을 해주는 것이다.

map

map은 배열안의 각 원소를 변환 할떄 사용 되며, 이 과정에서 새로운 배열이 만들어진다.

예를 들어서 다음과 같은 배열이 있다고 가정해보자.

const array = [1, 2, 3, 4, 5, 6, 7, 8];

만약에 배열 안의 모든 숫자를 제곱해서 새로운 배열을 만들고 싶다면 어떻게 해야할까? map 함수를 사용하지 않고 우리가 지금까지 배운 지식들을 사용하면 다음과 같이 구현할수 있다.

const array = [1, 2, 3, 4, 5, 6, 7, 8];

const squared = [];
for (let i = 0; i < array.length; i++) {
  squared.push(array[i] * array[i]);
}

console.log(squared);

또는 방금 배운 forEach 를 쓰면 다음과 같이 구현할수도 있다.

const array = [1, 2, 3, 4, 5, 6, 7, 8];

const squared = [];

array.forEach(n => {
  squared.push(n * n);
});

console.log(squared);

결과는 다음과 같다.

[1, 4, 9, 16, 25, 36, 49, 64];

만약 map을 사용하면 이를 더 짧은 코드를 사용하여 구현할수 있다.

const array = [1, 2, 3, 4, 5, 6, 7, 8];

const square = n => n * n;
const squared = array.map(square);
console.log(squared);

map함수의 파라미터로는 변화를 주는 함수를 전달해 준다. 이를 변화함수라고 부르도록 하겠다.

현재 우리의 변화함수 square는 파라미터 n을 받아와서 이를 제곱해 준다.

array map함수를 사용 할때 square를 변화함수로 사용함으로서, 내부의 모든 값에 대하여 제곱을 해서 새로운 배열을 생성하였다.

변화 함수를 꼭 이름을 붙여서 선언 할 필요는 없다. 코드를 다음과 같이 작성해도 된다.

const squared = array.map(n => n * n);
console.log(squared);

indexOf

indexOf는 원하는 항목이 몇번째 원소인지 찾아주는 함수이다.

예를 들어 다음과 같은 배열이 있을 때,

const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];

토르가 몇번째 항목인지 알고 싶다고 가정해보자.

그렇다면 이렇게 입력할수 있다.

const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];
const index = superheroes.indexOf('토르');
console.log(index);

결과는 2가 나타난다.

index값은 0부터 시작하기 때문에  0: 아이언맨 1: 캡틴 아메리카 2: 토르 이렇게 되서 2라는 값이 나타나는 것이다.

findIndex

만약에 배열 안에 있는 값이 숫자, 문자열, 또는 불리언이라면 찾고자 하는 항목이 몇번째 원소인지 알아내려면 indexOf를 사용하면 된다. 하지만, 배열 안에 있는 값이 객체이거나, 배열이라면 indexOf로 찾을수 없다.

예를 들어서 다음과 같은 배열이 있다고 가정해보자.

const todos = [
  {
    id: 1,
    text: '자바스크립트 입문',
    done: true
  },
  {
    id: 2,
    text: '함수 배우기',
    done: true
  },
  {
    id: 3,
    text: '객체와 배열 배우기',
    done: true
  },
  {
    id: 4,
    text: '배열 내장함수 배우기',
    done: false
  }
];

여기서 만약 id가 3인 객체가 몇번째인지 찾으려면, findIndex함수에 검사하고자 하는 조건을 반환하는 함수를 넣어서 찾을수 있다.

const todos = [
  {
    id: 1,
    text: '자바스크립트 입문',
    done: true
  },
  {
    id: 2,
    text: '함수 배우기',
    done: true
  },
  {
    id: 3,
    text: '객체와 배열 배우기',
    done: true
  },
  {
    id: 4,
    text: '배열 내장함수 배우기',
    done: false
  }
];

const index = todos.findIndex(todo => todo.id === 3);
console.log(index);

결과는 2가 나온다.

 

find

find함수는 findIndex랑 비슷한데, 찾아낸 값이 몇번쨰인지 알아내는 것이 아니라, 찾아낸 값 자체를 반환한다.

const todos = [
  {
    id: 1,
    text: '자바스크립트 입문',
    done: true
  },
  {
    id: 2,
    text: '함수 배우기',
    done: true
  },
  {
    id: 3,
    text: '객체와 배열 배우기',
    done: true
  },
  {
    id: 4,
    text: '배열 내장함수 배우기',
    done: false
  }
];

const todo = todos.find(todo => todo.id === 3);
console.log(todo);

결과는 다음과 같다

{id: 3, text: "객체와 배열 배우기", done: true}

filter

filter함수는 배열에서 특정 조건을 만족하는 값들만 따로 추출하여 새로운 배열은 만든다. 예를 들어서 방금 만들었던 todos배열에서 done값이 false인 항목들만 따로 추출해서 새로운 배열을 만들어 보자.

const todos = [
  {
    id: 1,
    text: '자바스크립트 입문',
    done: true
  },
  {
    id: 2,
    text: '함수 배우기',
    done: true
  },
  {
    id: 3,
    text: '객체와 배열 배우기',
    done: true
  },
  {
    id: 4,
    text: '배열 내장함수 배우기',
    done: false
  }
];

const tasksNotDone = todos.filter(todo => todo.done === false);
console.log(tasksNotDone);

결과는 다음과 같다.

[
  {
    id: 4,
    text: '배열 내장 함수 배우기',
    done: false
  }
];

filter함수에 넣는 파라미터는 조건을 검사하는 함수를 넣어주며, 이함수의 파라미터로 각 원소의 값을 받아오게 된다.

방금 우리가 작성한 코드는 이렇게 입력할수도 있다.

const tasksNotDone = todos.filter(todo => !todo.done);

filter에 넣어준 함수에서true를 반환하면 새로운 배열에 따로 추출을 해주는데 만약 todo.done값이 false라면, !false가 되고 이 값은 true이기 때문에, 이전의 todo.tone===false와 똑같이 작동하게 된다.

splice

splice는 배열에서 특정 항목을 제거할때 사용한다.

const numbers = [10, 20, 30, 40];

위 배열에서 30을 지운다고 가정해보자. 그러면, 30이 몇번째 index인지 알아낸 이후, 이를 splice를 통해 지워줄수 있다.

const numbers = [10, 20, 30, 40];
const index = numbers.indexOf(30);
numbers.splice(index, 1);
console.log(numbers);

결과는 다음과 같다.

[10, 20, 40]

shift와 pop

shift와 pop은 비슷하지만, 다르다.

shift는 첫번째 원소를 배열에서 추출해준다.(추출하는 과정에서 배열에서 해당 원소는 사라진다.)

const numbers = [10, 20, 30, 40];
const value = numbers.shift();
console.log(value);
console.log(numbers);

결과는 다음과 같다.

10
[20, 30, 40]

이번엔 pop을 해보자

const numbers = [10, 20, 30, 40];
const value = numbers.pop();
console.log(value);
console.log(numbers);

결과는 다음과 같다.

40
[10, 20, 30]

pop은 push의 반대로 생각하면 된다. push는 배열의 맨 마지막에 새 항목을 추가하고, pop은 맨 마지막 항목을 추출한다.

unshift

unshift는 shift의 반대이다.

배열의 맨앞에 새 원소를 추가한다.

const numbers = [10, 20, 30, 40];
numbers.unshift(5);
console.log(numbers);

결과는 다음과 같다.

[5, 10, 20, 30, 40]

concat

concat은 여러개의 배열을 하나의 배열로 합쳐준다.

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const concated = arr1.concat(arr2);

console.log(concated);

결과는 다음과 같다.

[1, 2, 3, 4, 5, 6];

concat함수는 arr1과 arr2에 변화를 주지 않는다.

join

join은 배열안의 값들을 문자열 형태로 합쳐준다.

const array = [1, 2, 3, 4, 5];
console.log(array.join()); // 1,2,3,4,5
console.log(array.join(' ')); // 1 2 3 4 5
console.log(array.join(', ')); // 1, 2, 3, 4, 5

reduce

reduce함수는 잘 사용 할줄 알면 정말 유용한 내장함수이다.

만약 주어진 배열에 대하여 총합을 구해야 되는 상황이 왔다고 가정해보자

이렇게 구현할수 있을 것이다.

const numbers = [1, 2, 3, 4, 5];

let sum = 0;
numbers.forEach(n => {
  sum += n;
});
console.log(sum);

결과는 15가 된다

여기서 sum을 계산하기 위해서 사전에 sum을 선언하고, forEach를 통해서 계속해서 덧셈을 해주었다.

reduce라는 함수를 사용하면 다음과 같이 구현 할수 있다.

const numbers = [1, 2, 3, 4, 5];
let sum = array.reduce((accumulator, current) => accumulator + current, 0);

console.log(sum);

reduce함수에는 두개의 파라미터를 전달한다. 첫번째 파라미터는 accumulator와 current를 파라미터로 가져와서 결과를 반환하는 콜백함수이고, 두번째 파라미터는 reude함수에서 사용할 초깃값이다.

여기서 accumulator는 누적된 값을 의미한다.

방금 작성한 함수를 다음과 같이 수정해보자.

const numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((accumulator, current) => {
  console.log({ accumulator, current });
  return accumulator + current;
}, 0);

console.log(sum);

이 코드의 실행 결과는 다음과 같다.

배열을 처음부터 끝까지 반복하면서 우리가 전달한 콜백함수가 호출이 되는데, 가장 처음엔 accmulator값이 0이다. 이 값이 0인 이유는 우리가 두번째 파라미터인 초깃값으로 0을 설정 했기 때문이다.

처음 콜백 함수가 호출되면, 0+1을 해서 1이 반환된다. 이렇게 1이 반환되면 그 다음 번에 콜백함수가 호출 될떄 accumulator값으로 사용된다.

콜백 함수가두번째로 호출 될 땐 1 + 2 를 해서 3이 되고, 이 값이 세번쨰로 호출될 때의 accumulator가 된다.

그래서 쭉 누적돼서 결과물 15가 나타나는 것이다.

reduce를 사용해서 평균도 계산 할수 있다. 평균을 계산 하려면, 가장 마지막 숫자를 더하고나서 배열의 length로 나누어 주어야 한다.

const numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((accumulator, current, index, array) => {
  if (index === array.length - 1) {
    return (accumulator + current) / array.length;
  }
  return accumulator + current;
}, 0);

console.log(sum);

결과를 3이 된다.

위 코드의 reduce에서 사용한 콜백 함수에서는 추가 파라미터로 index와 array를 받아 왔다. index는 현제 처리하고 있는 항목이 몇번째 인지 가르키고, array는 현재 처리하고 있는 배열 자신을 의미한다.