오늘은 조건 및 분기를 깔끔하고 간단하게 다루는 방법에 대해 알아보자.
Truthy
란 불리언을 기대하는 문맥에서 true
로 평가되는 값을 말한다. 아래 Falsy
한 값으로 정의된 값이 아니면 모두 Truthy
로 평가된다.
Falsy 값 8가지
false
,0
,-0
,0n
,NaN
,''
,null
,undefined
이러한 Truthy
와 Falsy
를 활용하여 아래처럼 조건문을 만들거나 분기 처리할 수 있다.
const str = 'hello'
if(str){
// true 로 취급된다! 그러므로 if 문 안의 코드가 실행된다.
}
const arr = []
if(arr.length){
// arr.length === 0 이다.
//false 로 취급되므로 if 문 안의 코드는 실행되지 않는다.
}
논리 연산자를 활용하면 훨씬 간단하게 조건문을 설정하고, 분기 처리할 수 있다.
&& : And 연산자
모든 조건이 참이면 뒤의 값 반환, 하나라도 거짓이면 거짓인 값 반환true && true // true true && false //false false && true //false false && false //false false&&'' //false true&&'' // '' 33&&44 //44 33&&false //false
|| : Or 연산자
모든 조건이 참이라면 앞의 값, 모든 조건이 거짓이라면 뒤의 값, 하나라도 참이면 참인 값 반환true || true // true true || false // true false || true // true false || false //false true||'' // true ''||false // false false||'' // ''
?? : Null 병합 연산자
앞에 오는 값이 null 또는 undefined이면 뒤에오는 값을, 아니라면 앞의 값을 반환null ?? true // true null ?? [] // [] null ?? NaN //NaN null ?? undefined //undefined undefined ?? false //false undefined ?? '' // '' undefined ?? undefined //undefined undefined ?? null // null '' ?? null // '' 55 ?? undefined //55
아래와 같이 단축 평가로 사용할 수 있다.
function fetchData(){
return state.data || 'Fetching...'
//state.data 가 있으면 return state.data
//state.data 가 없으면 return 'Fetching...'
}
function Welcome(){
return (
{isLogin && <h1>hello, {userName}</h1>}
// isLogin이 true면 뒷 부분도 나타남
// isLogin이 false면 뒷 부분도 안나타남
)
}
function Hello(name){
return 'Hello ' + (name ?? '이름 없음')
}
Hello('영희') // Hello 영희
Hello('') // Hello
Hello() // Hello 이름 없음
⊕
||
와??
의 차이점
null과 undefined, 숫자 0을 구분 지어 다뤄야 할 때 이 차이점은 매우 중요한 역할을 한다!let height = 0; console.log(height || 100); // 100 console.log(height ?? 100); // 0
height || 100
은 height에 0을 할당했지만 0을 falsy 한 값으로 취급했기 때문에 null이나 undefined를 할당한 것과 동일하게 처리한다.반면
height ?? 100
의 평가 결과는 height가 정확하게 null이나 undefined일 경우에만 100이 된다.따라서
null
과undefined
만 예외 처리해주고 싶을때는??
를 써야 한다!
부정 연산자를 붙이면 두 번 생각을 해야하므로 되도록 긍정 조건문을 사용하고, 필요한 경우에는 각 조건마다 부정 연산자!
를 붙여 사용하자. (괄호로 긍정 조건을 묶어 한 번에 부정 연산자를 사용하면 사고하기 더 어렵다.)
//Bad case
if(!(isUser&&isAdult)){
// isUser 와 isAdult 둘 다 참인 경우의 반대 상황에서 실행
// 즉, isUser 와 isAdult 모두 false 인 경우 실행
}
// Better case : 괄호를 벗기고 각 조건에 부정연산자 사용
if(!isUser&&!isAdult){
// isUser 와 isAdult 모두 false 인 경우 실행
}
if/else문의 대체재.
앞에서부터조건문
,물음표(?)
,조건문이 참(truthy)일 경우 실행할 표현식
,콜론(:)
,조건문이 거짓(falsy)일 경우 실행할 표현식
으로 이루어진다.condition ? 'condition이 true 일 경우' : 'condition이 false 일 경우'
간단한 조건을 다룰 때에는 짧은 코드로 같은 효과를 낼 수 있기 때문에 if/else 대신 삼항연산자를 많이 사용한다. 특히 리엑트 JSX 내부에서는 if/else 문을 사용할 수 없기 때문에 삼항 연산자가 많이 사용된다.
function Level(level){
return (
<div className={level>10 ? 'green' : 'yellow'}>{level}</div>
)
}
조건이 길어질 경우에는 ?
와 :
를 기준으로 줄바꿈을 해주면 보기 편하다. 이중으로 삼항 연산자를 사용하는 경우에는 괄호로 범위를 묶어주면 우선적으로 살펴볼 수 있도록 사고를 돕는다.
condition1
? (condition2 ? '두개 다 만족' : 'condition1만 만족')
: 'condition1 불만족'
⊕ 단, 지나친 숏코딩은 지향하자! 코드는 결국 사람이 읽는 것이다. 짧고 간략한 코드를 지향하는 것은 쉽게 코드를 파악하고 이해하기 위함이다. 지나친 숏코딩으로 인해 가독성이 사라진다면 의미가 없다.
연산자 우선순위
라는 것이 있다. 그러나 이것을 일일히 외워서 사용하기는 쉽지 않으므로, 괄호를 사용하여 명시적으로 우선순위를 표현 및 설정해주는 것이 좋다.
function (){
return a / ( b * c )
}
if((isLogin && isVaildToken) || isUser){
}
else 와 else if 를 습관적으로 사용하는 경우가 있는데, 불필요한 경우가 대반사이므로 되도록 사용을 지양하는게 좋다.
특히 else if 의 경우 else문 내부에서 if 문을 한 번 더 실행하는 것과 같으므로 그냥 if 문만 사용해도 충분히 의도대로 작동하는 코드를 작성할 수 있다.
if(num<=5){
return 'not bad'
}else if(num<=50){
return 'good'
}else{
return 'great'
}
// 리펙토링
if(num<=5){
return 'not bad'
}
if(num<=50){
return 'good'
}
return 'great'
예외 상황 또는 특정 상황이 있다면 Early Return 으로 빠르게 종료해주는 것이 좋다. 함수를 빠르게 종료할 수 있으며, 인간이 사고하기 훨씬 편하다.
function login(isLogin, isVaildToken, user){
//로그인 하지 않은 유저인 경우
if(!isLogin){
//유효한 토큰을 가진 경우
if(isVaildToken){
//닉네임이 없는 경우 회원가입으로 보내기
if(!user.nickName){
return registerUser(user)
// !isLogin && isVaildToken && user.nickName 인 경우
}else{
refreshToken()
return '로그인 성공'
}
//토큰이 없는 경우
}else{
throw new Error('No token')
}
}
}
function login(isLogin, isVaildToken, user){
//로그인 한 경우 얼리 리턴
if(isLogin){
return
}
// 유효하지 않은 토큰 가진 경우 에러 던지고 얼리 리턴
if(!isVaildToken){
throw new Error('No token')
}
// 이름이 없는 경우 회원가입으로 얼리 리턴
if(!user.nickName){
return registerUser(user)
}
// 위의 경우의 수 모두 아닌 경우에는 리프레쉬 토큰 + 로그인 성공
refreshToken()
return '로그인 성공'
}
Clean Code(클린 코드)
/ 로버트 C. 마틴 / 2013.12.24.클린코드 자바스크립트
/ Poco Jang / 2023. 5.