본문 바로가기

프로그래밍/JavaScript

배열의 내장함수

JavaScript에서 유용하게 쓸 수 있는 내장함수

 

forEach

  • forEach는 기존에 여러 언어에서 두루 쓰이는 for문을 대체할 수 있는 가장 간편한 내장함수다.
const list = [1, 2, 3, 4, 5, 6];

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

for문을 사용했을 때의 코드

const list = [1, 2, 3, 4, 5, 6];

list.forEach(value => console.log(value));

내장함수인 forEach를 사용했을 때의 코드

  • 위 두 코드와 같이 forEach를 사용하게 되면 기존의 코드를 더 간략하게 축약할 수 있게 된다.

 

map

  • map함수는 매개변수로 함수를 받을 수 있으며 이 함수에 따라 배열의 각 요소들의 값을 변화시킬 수 있다.
//배열의 각 요소들을 제곱한다.
const list = [1, 2, 3, 4, 5, 6];
const resultList = [];

list.forEach((value) => {
    resultList.push(value ** 2);
});

console.log(resultList);

forEach로 구현했을 때의 코드

const list = [1, 2, 3, 4, 5, 6];
const resultList = list.map(value => value ** 2);

console.log(resultList);

map을 이용했을 때의 코드

  • map의 매개변수를 통해 기존에 선언되어있던 배열의 요소들을 변조해줄 수 있다. 이를 통해 이전에 쓰이던 for나 forEach보다 더 간략하게 코드를 작성할 수 있게 된다.

 

indexOf

  • 찾고자하는 값이 해당 배열의 몇 번째 인덱스에 존재하는지 찾는 것을 도와주는 함수다.
const list = ['a', 'b', 'c', 'd', 'e', 'f'];

//콘솔에 'd'가 저장되어 있는 인덱스인 3이 출력된다.
console.log(list.indexOf('d'));

 

findIndex

  • indexOf에 더해 배열 내부의 값이 객체나 배열일 경우에도 원하는 값의 인덱스를 찾고자 할 때 사용되는 함수다.
const blocks = [
    {
        name: 's', //네모
        center: false,
        numberCode: 1,
        color: 'red',
        currentShapeIndex: 0
    }, {
        name: 't', //T모양
        center: true,
        numberCode: 2,
        color: 'blueviolet',
        currentShapeIndex: 0
    }, {
        name: 'z', //z자
        center: true,
        numberCode: 3,
        color: 'orenge',
        currentShapeIndex: 0
    },
    {
        name: 'rz', //반대z자
        center: true,
        numberCode: 4,
        color: 'skyblue',
        currentShapeIndex: 0
    }
}

const search = blocks.findIndex(value => value.color === 'orange');

//findIndex의 결과로 해당 속성의 값이 둘어있는 인덱스인 2가 출력된다.
console.log(search);

 

  • findIndex를 이용해 해당 값의 인덱스를 찾을 때 만일 해당 값을 가진 인덱스가 여러개라면 가장 먼저 찾은 인덱스가 반환된다.

 

find

  • findIndex와 같은 프로세스를 가지고 있으나 반환하는 값이 인덱스가 아닌 해당 인덱스의 값 전체를 반환하게 된다는 차이가 있다.
const blocks = [
    {
        name: 's', //네모
        center: false,
        numberCode: 1,
        color: 'red',
        currentShapeIndex: 0
    }, {
        name: 't', //T모양
        center: true,
        numberCode: 2,
        color: 'blueviolet',
        currentShapeIndex: 0
    }, {
        name: 'z', //z자
        center: true,
        numberCode: 3,
        color: 'orenge',
        currentShapeIndex: 0
    },
    {
        name: 'rz', //반대z자
        center: true,
        numberCode: 4,
        color: 'skyblue',
        currentShapeIndex: 0
    }
];

const search = blocks.find(index => index.name === 'z');

//name속성이 'z'에 해당하는 인덱스의 모든 값이 콘솔에 출력된다.
console.log(search);

 

  • find를 이용해 값을 불러온 후 추가적으로 원하는 속성을 추가로 넣어 해당 값만 뽑아내는 방식도 사용할 수 있다.
...

const search = blocks.find(index => index.name === 'z').color;

//해당하는 요소의 color속성값만 출력된다.
console.log(search);

 

filter

  • filter함수는 기준 배열 내에서 주어진 조건을 만족하는 요소들만 따로 뽑아 새로운 배열을 만드는 역할을 한다.
const blocks = [
    {
        name: 's', //네모
        center: false,
        numberCode: 1,
        color: 'red',
        currentShapeIndex: 0
    }, {
        name: 't', //T모양
        center: true,
        numberCode: 2,
        color: 'blueviolet',
        currentShapeIndex: 0
    }, {
        name: 'z', //z자
        center: true,
        numberCode: 3,
        color: 'orenge',
        currentShapeIndex: 0
    },
    {
        name: 'rz', //반대z자
        center: true,
        numberCode: 4,
        color: 'skyblue',
        currentShapeIndex: 0
    }
];

//value.center === false는 !value.center와 같은 의미를 가진다.
const filteredBlock = blocks.filter(value => value.center === false);

//center속성의 값이 false가 아닌 모든 요소들이 제거된 후 새로운 값들이 새 배열 변수에 저장된다.
console.log(filteredBlock);

 

splice

  • splice에는 두 개의 매개변수를 사용할 수 있으며 첫 번째 매개변수에는 몇 번째 인덱스부터 지울지를, 두 번째 매개변수에는 해당 인덱스로부터 몇 개의 요소를 지울지에 대한 명령을 기록하게 된다.
const list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];

//3번 인덱스를 포함해 뒤로 5개를 지우도록 명령한다.
list.splice(3, 5);

console.log(list);

 

  • 인덱스를 직접 입력하는 대신 indexOf나 findIndex 등을 활용해 원하는 값에 대한 인덱스값을 먼저 추출한 후 splice를 진행하는 방법도 있다.
...

const index = list.indexOf(9);
//list.splice(list.indexOf(9), 4)와 같이 축약해서 작성해도 무방하다.
list.splice(index, 4);

console.log(list);

 

slice

  • splice와 같은 기능을 가지고 있지만 기존에 존재하던 배열을 건드리지 않고 새로운 배열을 생성하여 결과값을 저장한다는 차이가 있다.
const list = [1, 2, 3, 4, 5];

const sliceList = list.slice(2, 2);

//기존에 존재하던 list배열은 내부 요소에 변화가 없음을 알 수 있다.
console.log(sliceList);
console.log(list);

 

shift & unshift

  • shift함수는 배열의 첫 번째 인덱스값을 해당 배열에서 제거하는 역할을 한다.
const list = [1, 2, 3, 4, 5];
const lose = list.shift();

//shift함수를 통해 추출된 값인 1이 출력된다.
console.log(lose);

 

  • shift함수는 가장 뒤의 요소를 추출해주는 pop()함수와는 정 반대의 기능을 한다고 보면 된다.
  • unshift는 shift와는 달리 가장 앞에 해당하는 값을 넣어주는 역할을 한다.
const list = [1, 2, 3, 4, 5];

list.unshift(10);

//가장 앞에 10이 추가된 [10, 1, 2, 3, 4, 5]가 출력된다.
console.log(list);

//아래와 같이 반복문을 활용해 여러개의 값을 배열의 앞에 추가해주는 방식도 사용 가능하다.
for (let i = 0; i < 5; i++) {
    list.unshift(i);
}

 

concat

  • concat함수는 여러 개의 배열들을 하나의 배열로 합쳐주는 역할을 한다.
const list1 = [1, 2, 3, 4];
const list2 = [5, 6, 7, 8];
const list3 = [2, 4, 6, 8];

const mixedList = list1.concat(list2.concat(list3));

//세 가지 배열이 모두 합쳐진 배열이 완성된다.
console.log(mixedList);

 

join

  • join함수는 배열 내의 요소들을 매개변수로 넣은 구분자를 기준으로 문자열 형태로 합치는 역할을 한다.
  • 만일 별다른 구분자를 매개변수에 입력하지 않게 되면 ,이 기본값으로서 지정된다.
const list = [1, 2, 3, 4];

//1,2,3,4
console.log(list.join());
//1234
console.log(list.join(''));
//1 | 2 | 3 | 4
console.log(list.join(' | '));
//1 & 2 & 3 & 4
console.log(list.join(' & '));

 

  • 임의의 문자열에 join함수와 split함수를 사용하게 되면 공백 없는 문자열을 만들어줄 수도 있다.
const line = 'Have a good day!';

const changedLine = line.split(' ').join('');

 

reduce

  • 사용하는 바에 따라 활용도가 무궁무진하게 변화할 수 있는 내장함수다.
  • 기본적으로는 map과 유사하게 함수를 매개변수로서 받게 된다.
  • 함수에는 두 가지 매개변수를 선언할 수 있으며 첫 번째 매개변수에는 함수에 대한 결과가 누적되어 저장되며 두 번째 매개변수는 reduce함수에서 사용하게 될 누적 변수의 초기값을 저장하게 된다.
const list = [1, 2, 3, 4, 5, 6];

let multifyList = list.reduce((accumulator, current) => accumulator * current, 1);

console.log(multifyList);

 

  • reduce함수에 의해 모든 배열의 요소들을 곱한 값이 multifyList변수에 저장된다.

 

한 가지 문제를 해결할 세 가지 방법

  • 숫자로 이루어진 배열이 있을 때 이를 10 보다 큰 요소들의 개수를 반환해주는 함수를 만든다.

1. forEach를 활용하는 방법

const func = (arr) => {
    let count = 0;
    arr.forEach((value) => {
        if (value > 10) {
            ++count;
        }
    });
    
    return count;
};

const list = func([1, 2, 3, 4, 5, 10, 20, 30, 40, 50]);
console.log(list);

 

2. filter를 활용하는 방법

const func = (arr) => {
    return arr.filter(value => value > 10).length;
};

const list = func([1, 2, 3, 4, 5, 10, 20, 30, 40, 50]);
console.log(list);

 

3. reduce를 활용하는 방법

const func = (arr) => {
    return arr.reduce((accumulator, current) => {
        if (current > 10) {
            return ++accumulator;
        } else { //else를 통해 예외상황을 확실하게 처리해주지 않으면 NaN이 결과로 출력되는 문제가 발생한다.
            return accumulator;
        }
    }, 0);
};

const list = func([1, 2, 3, 4, 5, 10, 20, 30, 40, 50]);
console.log(list);

 

  • reduce를 사용할 때는 return을 확실하게 기입하여 결과를 저장하는 것에 더해 조건문을 사용하고자 한다면 else를 확실하게 사용해 어느 조건에도 포함되지 않을 때의 처리도 지정해두는 것이 중요하다는 것을 알 수 있었다.
  • 그냥 위 세가지 방식을 비교해보았을 때 reduce를 사용하는 것이 filter나 map, forEach를 사용하는 것에 비해 어떤 면이 더 유리한 지 확신이 되지 않는다.
  • reduce는 코드가 더 복잡해질수록 점점더 재사용성 등의 효율이 증가하게 된다.
const list = [1, 2, 3, 4, 5, 6];

const resultList = []

const func = (accumulator, current) => {
    if (current % 2 !== 0) {
        accumulator.push(current * 2);
    }
    return accumulator;
};

const resultWithReduce = list.reduce(func, resultList);
const resultWithFilterAndMap = list.filter(value => value % 2 !== 0).map(value => value * 2);

 

  • reduce를 사용하게 되면 배열을 한 번만 순회하는 중에 문제가 해결되는 반면, filter와 map은 조건에 맞는 요소를 추출하는 과정과 해당 요소를 곱하는 과정을 거치며 배열을 두 번 순회하게 되어 효율이 떨어지는 것을 볼 수 있다.
  • reduce를 사용함에 있어 드러나는 또다른 장점으로는 문제 해결을 위해 정의해둔 함수를 다른 코드에서도 재사용할 수 있게 된다는 것이다.

'프로그래밍 > JavaScript' 카테고리의 다른 글

프토토타입 & 클래스  (0) 2019.12.07
자바스크립트 문제 풀이 (2)  (0) 2019.11.28
자바스크립트 문제 풀이 (1)  (0) 2019.11.26
var과 let, const  (0) 2019.08.22
this  (0) 2019.08.21