https://amberley.dev/blog/2020-09-07-conditionally-add-to-array-or-obj/
해당 블로그의 글을 요약했습니다. 더 정확한 내용을 알기 위해서는 첨부해놓은 블로그의 글을 참고하시기를 바랍니다.
const flagObjTrue = true;
const flagObjFalse = false;
const flagArrTrue = true;
const flagArrFalse = false;
자바스크립트의 객체 혹은 배열에 조건부로 값을 추가하고 싶은 경우 보통 다음과 같은 방법을 많이 쓰게 됩니다.
const obj = {};
const arr = [];
if (flagObjTrue) {
obj.name = 'dongkyun';
}
if (flagObjFalse) {
obj.gender = 'male';
}
if (flagArrTrue) {
arr.push('dongkyun');
}
if (flagArrFalse) {
arr.push('male');
}
obj // { name: 'dongkyun' }
arr // ['dongkyun']
개인적으로 해당 코드를 봤을 때 단순한 블록문이 너무 많이 반복되고 있다는 느낌이 들었습니다. 때문에 어떻게 깔끔하게 표현할 수 있을 지에 대한 고민을 하게 되었습니다.
const obj = {
...(flagObjTrue && { name: 'dongkyun' }),
...(flagObjFalse && {gender: 'male' })
}
const arr = [
...(flagArrTrue ? ['dongkyun'] : []),
...(flagArrFalse ? ['male'] : [])
]
obj // { name: 'dongkyun' }
arr // ['dongkyun']
다음과 같이 자바스크립트의 spread operator
를 활용하면 조금은 더 깔끔한 느낌의 코드를 작성할 수 있습니다.
배열의 경우에도
&& 연산자
를 활용하면 코드가 더 깔끔해질 것 같은데 왜ternaey operator
를 사용하는건가요?
&& 연산자
를 사용할 수 없기 때문입니다.
기본적으로 spread operator
는 iterable object
에만 사용이 가능합니다. 참고
배열의 경우 iterable object
이지만, 객체의 경우 iterable object
가 아닙니다.
하지만 최근 TC39 Proposal을 통해 객체 리터럴 내부에서의 스프레드 문법의 사용이 허가되었습니다.
때문에 객체 리터럴은 iterable 하지 않음에도 불구하고 다음과 같은 표현이 가능합니다.
const obj = { a: 1, b: 2 };
const copyObj = { ...obj };
copyObj // { a: 1, b: 2}
다시 위의 예제를 이해하기 쉬운 형태 + arr
의 경우에도 && 연산자
를 사용한 형태로 변환하여 확인해보겠습니다.
const obj = { => 1
...{ name: 'dongkyun' },
...false
}
// const arr = [
// ...(flagArrTrue && ['dongkyun']),
// ...(flagArrFalse && ['male'])
// ]
const arr = [ => 2
...['dongkyun'],
...false
]
이제 왜 && 연산자
를 사용할 수 없는지 그 이유가 보이시나요?
1번의 경우 객체 리터럴 내부에서는 iterable object
가 아닌 경우에도 spread operator
의 사용을 허가합니다. 때문에 iterable object
가 아닌 false
값에 spread operator
를 사용하더라도 에러가 발생하지 않습니다. (대신 그 어떠한 값도 남기지 않습니다.)
반면 2번의 경우 객체 리터럴이 아닌 배열 리터럴 내부에서 iterable object
가 아닌 false
값에 대해 spread operator
를 사용하였습니다. 이로 인해 Uncaught TypeError: false is not iterable
에러가 발생하게 됩니다.
모두가 알고 있듯이 컨벤션에 정답은 없습니다. 당연히 해당 글에서 제안하고 있는 코드의 형태 또한 하나의 방법일 뿐 정답은 아닙니다. 해당 형태를 사용하고 말고는 본인의 선택이지만, 그 선택에 대한 기준은 분명했으면 좋겠습니다.