오늘은 filter() 메소드에 대해 알아보자.
우선 filter()는 배열의 메소드이다.
MDN의 설명은 이러하다.
filter()는 배열 내 각 요소에 대해 한 번 제공된 callback 함수를 호출해, callback이 true로 강제하는 값을 반환하는 모든 값이 있는 새로운 배열을 생성합니다. callback은 할당된 값이 있는 배열의 인덱스에 대해서만 호출됩니다; 삭제됐거나 값이 할당된 적이 없는 인덱스에 대해서는 호출되지 않습니다. callback 테스트를 통과하지 못한 배열 요소는 그냥 건너뛰며 새로운 배열에 포함되지 않습니다.
callback은 다음 세 인수와 함께 호출됩니다:
요소값요소 인덱스순회(traverse)되는 배열 객체
thisArg 매개변수가 filter에 제공된 경우, 호출될 때 그 값은 callback의 this 값으로 전달됩니다. 그 이외에, undefined값도 callback의 this 값으로 쓰기 위해 전달됩니다. 결국 callback에 의해 관찰될 수 있는 this 값은 this를 결정하는 함수의 평소 규칙에 따라 결정됩니다.
filter()는 호출되는 배열을 변화시키지(mutate) 않습니다.
filter()에 의해 처리되는 요소의 범위는 callback의 첫 호출 전에 설정됩니다. filter() 호출 시작 이후로 배열에 추가된 요소는 callback에 의해 방문되지 않습니다. 배열의 기존 요소가 변경 또는 삭제된 경우, callback에 전달된 그 값은 filter()가 그 요소를 방문한 시점에 값이 됩니다; 삭제된 요소는 반영되지 않습니다.
* MDN 참고
역시나 어렵게 말이 써져 있다.
내가 본 결과 filter()는
인자로 콜백함수를 받는데, 그 함수는 걸러내고 싶은 값의 조건이 입력된 값이다. 따라서 특정 값을 걸러내는 역할을 한다.
함수의 문법
arr.filter(callback(element[, index[, array]])[, thisArg])
배열의 메소드이기 때문에 arr은 배열이다.
filter()에 인자는 함수를 받는데
그 안에는
element: 처리해야할 현재 요소
index: 처리해야할 요소의 인덱
array: filter를 호출한 배열
thisArg: callback을 실행할 때 this로 사용하는 값
이러한 것들을 받는다.
역시나 어렵다.
백문이불여일타
간단한 코드 예시로 알아보자.
function isBigEnough(value) {
return value >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered 는 [12, 130, 44]
위 코드에서 isBigEnough() 함수는 10보다 크거나 같은 값을 확인한다.
정확히는 [12, 5, 8, 130, 44] 배열 안에 있는 값 중 10보다 크거나 같은 값을 찾아서 결과로 내놓는다.
따라서 var filltered의 최종 값은 [12, 130, 44]이다.
다음 예시를 보자.
var arr = [
{ id: 15 },
{ id: -1 },
{ id: 0 },
{ id: 3 },
{ id: 12.2 },
{ },
{ id: null },
{ id: NaN },
{ id: 'undefined' }
];
var invalidEntries = 0;
function isNumber(obj) {
return obj !== undefined && typeof(obj) === 'number' && !isNaN(obj);
}
function filterByID(item) {
if (isNumber(item.id) && item.id !== 0) {
return true;
}
invalidEntries++;
return false;
}
var arrByID = arr.filter(filterByID);
console.log('Filtered Array\n', arrByID);
// Filtered Array
// [{ id: 15 }, { id: -1 }, { id: 3 }, { id: 12.2 }]
console.log('Number of Invalid Entries = ', invalidEntries);
// Number of Invalid Entries = 5
위 코드는 객체데이터를 걸러 주는 코드이다.
다소 복잡하게 느낄 수 있을 것 같다.
하지만 우리는 filter()를 공부 하고 있다는 것을 잊지말자.
위 코드에서
var arrByID = arr.filter(filterByID);
이 코드를 잘 봐주면 좋을 것 같다.
처음 예시를 들었던 코드와 공통점을 찾은 것 같나?
아니면 다른 예시를 한번 더 보자.
// 숫자 배열을 정의
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// 필터링할 조건을 담은 함수를 정의
function isEven(num) {
return num % 2 === 0;
}
// filter() 메소드에 외부 함수(isEven)를 인자로 넘겨서 필터링
const evenNumbers = numbers.filter(isEven);
// 결과 출력
console.log(evenNumbers); // 출력: [2, 4, 6, 8, 10]
자, 여기서도 보이는가?
그렇다. filter안에 인자는 콜백 함수를 받지만 함수를 따로 만들어서 인자로 넣는다.
간단한 함수는 직접 넣어서 사용하기도 하는데 가독성이 떨어진다 싶으면 따로 빼는게 좋다.
filter()메소드가 필요한 경우를 간단히 몇가지 알아보자.
1. 데이터 필터링
2. 검색 기능
3. 조건부 렌더링
4. 데이터 전처리
5. 중복 제거
간단히 이러한 경우 많이 사용하는 것 같다.
간단히 검색 기능에 대한 예시를 들어보겠다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="keywords" content="basic" />
<meta name="description" content="basic" />
<link rel="shortcut icon" href="" />
<link rel="stylesheet" href="./css/reset.css">
<link rel="stylesheet" href="./css/index.css">
<title>basic</title>
</head>
<body>
<h1>검색 기능 예시</h1>
<input type="text" id="searchInput" placeholder="검색어를 입력하세요">
<ul id="resultList"></ul>
<script src="./js/jquery-3.6.0.min.js"></script>
<script src="./js/index.js"></script>
</body>
</html>
위 코드는 HTML코드이다.
@charset "UTF-8";
body {
font-family: Arial, sans-serif;
margin: 20px;
}
h1 {
color: #333;
}
input[type="text"] {
padding: 5px;
margin-bottom: 10px;
}
ul {
list-style: none;
}
li {
margin-bottom: 5px;
}
위 코드는 이쁘지는 않지만 그래도 작게나마 CSS를 넣어봤다.
const data = [
'Apple', 'Banana', 'Cherry', 'Grapes', 'Kiwi', 'Orange', 'Pear', 'Strawberry'
];
const searchInput = document.getElementById('searchInput');
const resultList = document.getElementById('resultList');
searchInput.addEventListener('input', handleSearch);
function handleSearch() {
const searchTerm = searchInput.value.trim().toLowerCase();
const filteredData = data.filter(item => item.toLowerCase().includes(searchTerm));
displayResults(filteredData);
}
function displayResults(results) {
resultList.innerHTML = '';
if (results.length === 0) {
const noResultItem = document.createElement('li');
noResultItem.textContent = '검색 결과가 없습니다.';
resultList.appendChild(noResultItem);
} else {
results.forEach(result => {
const listItem = document.createElement('li');
listItem.textContent = result;
resultList.appendChild(listItem);
});
}
}
handleSearch() 함수 안에 filter()메소드가 사용 되었다.
다음에 기회가 되면 더 자세히 한번 다뤄보고 싶은 메소드이다.