[JS] 객체에 조건부로 요소 추가하기

장동균·2022년 9월 18일
0
post-custom-banner

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 operatoriterable 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 에러가 발생하게 됩니다.


마무리

모두가 알고 있듯이 컨벤션에 정답은 없습니다. 당연히 해당 글에서 제안하고 있는 코드의 형태 또한 하나의 방법일 뿐 정답은 아닙니다. 해당 형태를 사용하고 말고는 본인의 선택이지만, 그 선택에 대한 기준은 분명했으면 좋겠습니다.

profile
프론트 개발자가 되고 싶어요
post-custom-banner

0개의 댓글