Array methods

Shin Yeongjae·2020년 6월 25일
0

Wecode

목록 보기
7/26

Array 메서드에는 여러가지가 있다. 그 중에서 정말 유용하기도 하고 많이 쓰이기도 하는 mapforEach에 대해서 정리해보려 한다.


메서드란?

먼저 메서드가 무엇인지를 알아야 한다. MDN에 따르면

메소드(method)는 객체의 속성인 함수이다. 두 가지 종류의 메소드가 있다. 객체 인스턴스에 의해 수행되는 태스크에 내장된 인스턴스 메소드 또는 오브젝트 생성자에서 직접 호출되는 태스크인 정적 메소드가 여기에 해당된다.

  • 참고
    자바스크립트 함수에서 그 자체는 객체이므로, 그런 맥락에서 메소드는 실제로 함수에 대한 객체 참조인 것이다.

실제로 개발자 도구 콘솔에서 window라고 입력하면 window 객체가 출력되는 것을 확인할 수 있다. window 객체 내에 수많은 키들이 포함되어 있는데 그 중에 Array라는 키의 Prototype을 확인해보면 우리가 사용하는 수많은 Array에 대한 메서드들이 함수의 형태로 저장된 것을 찾아볼 수 있다.

이것이 잘 이해가 되지 않는다면 직접 객체를 만들어 그에 대한 키값으로 함수를 입력해서 실행해볼 수 있다.

const obj = {
  name: 'John',
  age: '24',
  fn: function() {
    return this.name;
  }
}

obj.fn(); // 'John'

obj라는 임의의 객체에 fn이라는 키를 할당해주고 그에 대한 value로 objname키의 value를 리턴하는 함수를 만들었다. obj.fn()이라는 형태가 익숙하지 않은가? 우리가 메서드를 쓰는 형태와 동일하다. arr.map(...) 이런식으로 말이다. 우리는 window라는 객체에 항상 접근하여 메서드를 사용하고 있는 것이다.

Array.prototype.map()

map 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 기존 배열은 그대로 두고 새로운 배열을 반환한다 immutable한 속성을 가지고 있기 때문이다. 그래서 반드시 callback 함수가 필요하다. callback 함수는 undefined를 포함하여 배열 값이 들어있는 요소에 대해서만 호출된다. 즉, 값이 삭제되거나 할당/정의되지 않는 인덱스에 대해서는 호출되지 않는다.

map을 활용하는 예시는 다음과 같다.

const nums = [100, 9, 30, 7];
const moreThan100 = nums => {
  const result = nums.map(num => {
    return num >= 100 ? true : false;
  })
  return result;
}

moreThan100(nums); // [true, false, false, false]
nums; // [100, 9, 30, 7]

map 메서드를 활용하여 기존 배열의 요소들이 100보다 클 경우 true로 변환하고 아니면 false로 변환하는 함수를 만들었다. 실제로 콘솔에 찍어보면 moreThan100이라는 함수를 실행하면 바뀐 값들이 출력되는것을 확인해볼 수 있다. nums를 찍어보면 기존 배열이 그대로 출력된다. 반복문을 사용하지 않아도 배열의 각 요소에 대해 callback 함수가 적용된다. 여러모로 편리한 메서드이다.

Array.prototype.forEach()

forEach 메서드도 map과 비슷한 기능을 한다. forEach 메서드는 주어진 함수를 배열의 각 요소에 대해 오름차순으로 실행한다. 삭제했거나 초기화하지 않은 인덱스 속성에 대해서는 실행하지 않는다. forEach도 마찬가지로 immutable한 속성을 가지고 있기 때문에 기존 배열은 건드리지 않고 새로운 배열을 반환한다.

forEach를 활용하는 예시는 다음과 같다.

let startWithNames = [];
let names = ['a', 'ab', 'cbb', 'ada'];

names.forEach(el => {   
  if (el.startsWith('a')) {     
    startWithNames.push(el);   
  } 
});

startWithNames; // ['a', 'ab', 'ada']
names; // ['a', 'ab', 'cbb', 'ada']

기존 배열 namesforEach를 활용하여 각 요소에 대해 a로 시작하는지 체크하여 true면 빈 배열 startWithNamespush하는 방식이다. 각 배열을 호출해보면 기존 배열은 변하지 않는 것을 확인할 수 있다. forEachfor문으로 변형할 수도 있다.

function foo(arr) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i].startsWith('a')) {
      startWithNames.push(arr[i]);
    }
  }
  return startWithNames;
}

foo(names); // ['a', 'ab', 'ada']
names; // ['a', 'ab', 'cbb', 'ada']

foo라는 함수는 forEach와 정확히 똑같은 기능을 하고 있는 것을 확인할 수 있다. 하지만 forEach에는 단점이 있는데 MDN에 따르면

예외를 던지지 않고는 forEach()를 중간에 멈출 수 없습니다. 중간에 멈춰야 한다면 forEach()가 적절한 방법이 아닐지도 모릅니다.
다음 방법으로는 조기에 반복을 종료할 수 있습니다.

  • 간단한 for 반복문
  • for...of, for...in 반복문
  • Array.prototype.every()
  • Array.prototype.some()
  • Array.prototype.find()
  • Array.prototype.findIndex()
    다른 배열 메서드 every(), some(), find(), findIndex()는 배열 요소를 판별 함수에 전달하고, 그 결과의 참/거짓 여부에 따라 반복의 종료 여부를 결정합니다.

배열의 모든 요소에 대해 함수를 실행하기 때문에 원하는 값이 나와도 예외 처리를 해주지 않으면 반복을 멈출수가 없다.

profile
문과생의 개발자 도전기

0개의 댓글