Array.prototype.includes()로 코드 가독성 개선하기

문제 상황

레거시 코드를 리팩토링하던 중 조건문이 지나치게 복잡한 부분을 발견했다.

if (status.indexOf('pending') !== -1 || 
    status.indexOf('processing') !== -1 || 
    status.indexOf('waiting') !== -1) {
  // ...
}

indexOf를 사용한 존재 여부 체크는 -1과의 비교가 필수인데, 이게 의도를 파악하기 어렵게 만들었다.

해결 방법

ES7(ES2016)에 추가된 Array.prototype.includes()를 사용해 개선했다.

const validStatuses = ['pending', 'processing', 'waiting'];

if (validStatuses.includes(status)) {
  // ...
}

가독성이 확실히 좋아졌다. includes는 boolean을 직접 반환하기 때문에 의도가 명확하게 드러난다.

추가 개선

권한 체크 로직에도 적용했다.

// Before
if (['admin', 'moderator', 'editor'].indexOf(userRole) > -1) {
  allowEdit = true;
}

// After
const canEditRoles = ['admin', 'moderator', 'editor'];
if (canEditRoles.includes(userRole)) {
  allowEdit = true;
}

주의사항

includes는 엄격한 동등성(===)을 사용한다. NaN 처리가 indexOf와 다르다는 점도 알아두면 좋다.

[NaN].includes(NaN); // true
[NaN].indexOf(NaN);  // -1

바벨 설정에 babel-polyfill이 포함되어 있어 IE11에서도 문제없이 동작했다. 팀 내 코딩 컨벤션에 indexOf 대신 includes 사용을 권장하는 항목을 추가했다.