Array Useful
ES6+ 등장 이전부터 사용되었던 배열 객체의 알아두면 유용한 메서드를 정리합니다.
Array.isArray()
전달된 데이터의 타입이 배열인지 확인하여 Boolean 값을 반환합니다.
const o = {};
const a = [];
Array.isArray(a); // true
Array.isArray(o); // false
Array.prototype.forEach()
배열의 각 아이템을 순환하여 처리할 때 유용합니다. for문 또는 for..of문을 사용할 수도 있습니다.
const items = ['아이템1', '아이템2', '아이템3'];
const copy = [];
// for문
for (let i=0, l=items.length; i<l; ++i) {
copy.push(items[i]);
}
// forEach 메서드
items.forEach(item => copy.push(item));
// for..of문
for (let item of items) {
copy.push(item);
}
forEach
메서드에 2번째 인자를 전달할 경우, 전달된 인자는 this
컨텍스트가 됩니다.
아래 코드는 class Counter
의 add
메서드 내부에 forEach
를 활용하면서
this
참조를 변경하는 예시입니다. this
를 변경함으로 add
메서드 내부의 this
는 Counter
클래스의
인스턴스를 참조하게 됩니다.
class Counter {
constructor() {
this.sum = 0;
this.count = 0;
}
add(array) {
array.forEach(function(item) {
this.sum += item;
++this.count;
}, this);
}
}
const obj = new Counter();
obj.add([9, 12, 3]);
console.log(obj.count); // 3
console.log(obj.sum); // 24
NOTE
화살표 함수 식을 사용하면 this
컨텍스트를 변경하지 않아도 됩니다.
화살표 함수 내부의 this
는 상위 컨텍스트를 참조하므로 아래 코드에서 this
는 Counter
클래스의
인스턴스입니다.
add(array) {
array.forEach(item => {
this.sum += item;
++this.count;
});
}
Array.prototype.map()
forEach
메서드와 유사하지만, 배열 객체의 아이템을 가공한 후 새로운 배열로 반환한다는 점이 다릅니다.
let items = ['아이템1', '아이템2', '아이템3'];
let copy = [];
// forEach 메서드를 사용할 경우
copy = items.forEach(item => {
return item.replace(/아이템/g,'');
});
console.log(copy); // undefined
// map 메서드를 사용할 경우
copy = items.map(item => {
return item.replace(/아이템/g,'');
});
console.log(copy); // ["1", "2", "3"]
NOTE
화살표 함수 식을 아래와 같이 간추려 표현하면 return
키워드를 생략할 수 있습니다.
copy = items.map(item => item.replace(/아이템/g,''));
Array.prototype.filter()
filter
메서드는 배열의 아이템 중 일부를 필터링(Filtering) 할 때 유용하게 사용됩니다.
const fruits = ['사과', '풋사과', '포도즙', '청포도', '망고', '바나나', '오렌지즙'];
/**
* 검색 조건에 따른 배열 필터링(쿼리)
*/
const filterFruits = (query) => {
return fruits.filter((fruit) => {
return fruit.includes(query);
});
};
console.log(filterFruits('사과')); // ['사과', '풋사과']
console.log(filterFruits('즙')); // ['포도즙', '오렌지즙']
NOTE
filterFruits
화살표 함수 식을 아래와 같이 점차적으로 함축하여 표현할 수도 있습니다.
- 매개변수의 괄호(
()
) 생략
const filterFruits = query => {
return fruits.filter(fruit => {
return fruit.includes(query);
});
};
- 함수의 중괄호(
{}
),return
키워드 생략
const filterFruits = query =>
fruits.filter(fruit =>
fruit.includes(query)
);
- 인라인(1줄) 변경
const filterFruits = query => fruits.filter(fruit => fruit.includes(query));
Array.prototype.sort()
sort
메서드는 배열의 아이템을 오름 차순, 내림 차순으로 정렬(Sortering) 할 때 유용하게 사용됩니다.
비교함수는 선택적으로 전달할 수 있습니다.
비교함수의 매개 변수는 현재 아이템과 다음 아이템으로, 아이템을 비교하여 정렬 순서를 변경합니다.
array.sort([compareFunction]);
주의!
sort
메서드는 새로운 배열을 반환하는 것이 아니므로,
데이터를 보존하려면 복사된 배열을 사용해야 합니다.
const originalArray = ['원본', '배열', '데이터'];
const copyedArray = [...originalArray];
숫자 정렬
a
-b
값이0
보다 작으면,a
가 먼저 배치 됩니다.a
-b
값이0
보다 크면,b
가 먼저 배치 됩니다.a
-b
값이0
일 경우,a
,b
의 배치에 변화가 없습니다.
const numbers = [11, 92, 7, 3, -12, 32, -2];
// 오름차순 정렬
const sortedASC = [...numbers].sort((n1, n2) => {
return n1 - n2;
});
console.log(sortedASC); // [-12, -2, 3, 7, 11, 32, 92]
NOTE
내림차순(DESC) 정렬의 경우는 비교함수 내 n2
에서 n1
을 빼면 됩니다.
const sortedDESC = [...numbers].sort((n1, n2) => {
return n2 - n1;
});
console.log(sortedDESC); // [92, 32, 11, 7, 3, -2, -12]
문자 정렬
a
>b
비교 값이1
이면,a
가 먼저 배치 됩니다.a
>b
비교 값이-1
이면,b
가 먼저 배치 됩니다.a
>b
비교 값이0
이면,a
,b
의 배치에 변화가 없습니다.
const fruits = ['사과', '풋사과', '포도즙', '청포도', '망고', '바나나', '오렌지즙'];
const orderedASC = [...fruits].sort((f1, f2) => {
return f1 > f2 ? 1 : f1 < f2 ? -1 : 0;
});
// ㄱ-ㅎ 순으로 정렬
console.log(orderedASC); // ["망고", "바나나", "사과", "오렌지즙", "청포도", "포도즙", "풋사과"]
NOTE
내림차순(DESC) 정렬의 경우는 반대로 비교함수 내 f1
보다 f2
가 클 경우, -1을 반환하도록 설정합니다.
const orderedDESC = [...fruits].sort((f1, f2) => {
return f1 > f2 ? -1 : f1 < f2 ? 1 : 0;
});
// ㅎ-ㄱ 순으로 정렬
console.log(orderedDESC); // ["풋사과", "포도즙", "청포도", "오렌지즙", "사과", "바나나", "망고"]
객체 정렬
문자 비교와 비슷하지만, 정렬하고자 하는 객체의 속성을 비교한 후 결과를 반환해야 합니다.
const members = [
{ name: '박유나', score: 42 },
{ name: '손상경', score: 87 },
{ name: '민준현', score: 78 },
{ name: '김소라', score: 91 },
{ name: '서진욱', score: 65 },
{ name: '나영진', score: 97 },
];
const orderMembersBy = (type='name', ascDesc=1) => {
const result = [...members].sort((m1, m2) => {
return m1[type] > m2[type] ? 1 : m1[type] < m2[type] ? -1 : 0;
});
return ascDesc >= 0 ? result : result.reverse();
};
orderMembersBy('name'); // 이름 ㄱ-ㅎ순 정렬
orderMembersBy('name', -1); // 이름 ㅎ-ㄱ순 정렬
orderMembersBy('score'); // 점수 낮은 순 정렬
orderMembersBy('score', -1); // 점수 높은 순 정렬
/* ---------------------------------------------------
// 검증
--------------------------------------------------- */
orderMembersBy('name').map(member => member.name);
// 출력: ["김소라", "나영진", "민준현", "박유나", "서진욱", "손상경"]
orderMembersBy('name', -1).map(member => member.name);
// 출력: ["손상경", "서진욱", "박유나", "민준현", "나영진", "김소라"]
orderMembersBy('score').map(member => member.score);
// 출력: [42, 65, 78, 87, 91, 97]
orderMembersBy('score', -1).map(member => member.score);
// 출력: [97, 91, 87, 78, 65, 42]