문법 에러가 발생하면 서비스 오류가 발생할 가능성이 있다.
따라서 문법을 잘 지키도록 노력해야 한다.
// JSX
<div id={if(condition) {'msg'}}>Hello World!</div>
// const obj = {id : if(condition) {'msg'}}
// 객체의 값으로 if문이 들어가고 있다.
// 객체의 값으로는 값만 들어갈 수 있기 때문에 위와 같이 작성하면 문법 에러가 발생한다.
React.createElement("div", {id: if(condition) {'msg'}}, "Hello World!");
// 아래처럼 삼항연산자로 작성하면 에러가 발생하지 않는다.
// 삼항연산자는 식이고, 이는 값으로 귀결되기 때문이다.
ReactDOM.render(<div id={condition ? 'msg' : null}>Hello World!</div>, mountNode);
아래에서 switch문을 사용했는데도 문법 에러가 발생하지 않는 이유는?
즉시 실행 함수
(IIFE) 를 사용했기 때문!
-> {} 내부에는 값이나 식만 들어갈 수 있는데, 즉시 실행 함수는 바로 값을 반환하기 때문에 사용할 수 있다.
<p>
{(() => {
switch (this.state.color) {
case "red":
return "#FF0000";
case "green":
return "#00FF00";
case "blue":
return "#0000FF";
}
})()}
</p>;
if문 대신 논리 연산자
를 사용할 수도 있다. (||, &&)
<p>{this.state.color || 'white'}</p>
배열에 있는 값을 화면에 하나씩 출력하고 싶을 때, for문을 사용하면 즉시 실행 함수로 만들어야 하고 값을 임시 변수에 저장해두었다 return해야 하기 때문에 굉장히 복잡해진다.
{
(() => {
const rows = [];
for (let i = 0; i < objectRows.length; i++) {
rows.push(<p key={i} data={objectRows[i]}></p>);
}
return rows;
})();
}
이럴때는 고차 함수
(map, filter 등)를 사용하면 간단하게 표현할 수 있다.
{
objectRows.map((obj, i) => <p key={i} data={obj}></p>);
}
JSX는 Babel로 트랜스파일링되면 객체로 바뀌는데, 객체 내부에는 값과 식만 넣을 수 있으므로 if문, for문, switch문 등을 넣을 수 없다. 따라서
논리 연산자, 삼항 연산자, 고차 함수, 즉시 실행 함수
를 활용하는 것이 좋다.
삼항연산자를 이용해 과도하게 숏코딩 하기 보다는 일관성
을 유지하는 것이 좋다.
조건문이 여러개일 때, 삼항연산자나 if문을 사용하기 보다는 switch문
을 사용하는 것이 좋다.
-> 가독성 측면에서 더 좋다.
()
를 이용해 우선순위 나타내주기const example = condition ? a === 0 ? 'zero' : 'positive' : 'negative'
// 아래처럼 괄호로 묶어 가독성을 높혀준다.
const example = condition ? (a === 0 ? 'zero' : 'positive') : 'negative'
alert()는 void를 반환하는 함수이다.
void는 '없음'을 나타내기 때문에 undefined가 들어가게 된다.
function alertMessage(isAdult) {
isAdult ? alert("입장 가능") : alert("입장 불가능");
}
위와 같이 나타내기 보다는 if문을 사용하는 것이 더 좋다.
function alertMessage(isAdult) {
if (isAdult) {
alert("입장 가능");
} else {
alert("불입장 가능");
}
}
삼항연산자는 값을 반환할 때 사용하는 것이 좋다.
function alertMessage(isAdult) {
const m = isAdult ? "입장 가능" : "입장 불가능";
}
조건에 따라 참, 거짓이 모두 필요한게 아니라 참이나 거짓만 필요한 경우에는
truthy/falsy
를 사용하는 게 좋다.
if (true)
if ({})
if ([])
if (42)
if ("0")
if ("false")
if (new Date())
if (-42)
if (12n)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)
if (false) {
// 도달할 수 없습니다.
}
if (null) {
// 도달할 수 없습니다.
}
if (undefined) {
// 도달할 수 없습니다.
}
if (0) {
// 도달할 수 없습니다.
}
if (-0) {
// 도달할 수 없습니다.
}
if (0n) {
// 도달할 수 없습니다.
}
if (NaN) {
// 도달할 수 없습니다.
}
if ("") {
// 도달할 수 없습니다.
}
이름이 비어있는지 확인해야 할 때
function printName(name) {
if (name === undefined || name === null) {
return "없음";
}
return "안녕" + name;
}
문자열은 truthy이기 때문에, !를 붙여 falsy로 만들어서 사용할 수 있다.
function printName(name) {
if (!name) {
return "없음";
}
return "안녕" + name;
}
AND
: 모두가 참이어야 참
OR
: 하나라도 참이면 참
true && false && '도달 x' // false를 만나면 멈춤
true || true || '도달 x' // 첫 true를 만나면 멈춤
단축 평가를 이용해 if문을 줄일 수 있다.
function fetchData() {
// if문 사용했을 때
if (state.data) {
return state.data;
} else {
return "Fetching...";
}
// 단축평가 사용했을 때
return state.data || "Fetching...";
}
function dog(name) {
let dogName;
if (name) {
dogName = name;
} else {
dogName = "냐옹";
}
return dogName + "입니다";
}
아래처럼 임시 변수를 만들지 않고 바로 나타낼 수 있다.
function dog(name) {
return (name || "냐옹") + "입니다";
}
중첩되는 if문이 있을 때
function getUserName(user, isLogin) {
if (isLogin) {
if (user) {
if (user.name) {
return user.name;
} else {
return "이름없음";
}
}
}
}
아래처럼 간결하게 나타낼 수 있다.
function getUserName(user, isLogin) {
if (isLogin && user) {
return user.name || "이름없음";
}
}
혹은 아래처럼도 가능하다.
function getUserName(user, isLogin) {
return isLogin && user && (user.name || "이름없음");
}
x가 0보다 큰 경우 첫 번째 메세지만 출력된다.
나열되어 있어서 두 번째 메세지도 출력될 것 같다는 착각을 줄 수 있다.
if (x >= 0) {
console.log("x는 0과 같거나 크다");
} else if (x > 0) {
console.log("x는 0보다 크다");
}
위의 식은 아래와 동일하다.
if (x >= 0) {
console.log("x는 0과 같거나 크다");
} else {
if (x > 0) {
console.log("x는 0보다 크다");
}
}
if (x >= 0) {
console.log("x는 0과 같거나 크다");
}
if (x > 0) {
console.log("x는 0보다 크다");
}
switch문
으로 작성한다.function getUserName(user) {
if (user.name) {
return user.name;
} else {
return "이름없음";
}
}
if문에서 return이 실행되면 어차피 아래 return문은 실행되지 않는다.
따라서 굳이 else를 사용하지 않고 아래처럼 나타내는게 좋다.
function getUserName(user) {
if (user.name) {
return user.name;
}
return "이름없음";
}
아래와 같이 복잡한 로직의 로그인 처리 코드가 있을 때
function login(isLogin, user) {
if (!isLogin) {
if (checkToken()) {
if (!user.name) {
return registerUser(user);
} else {
refreshToken();
return "로그인 성공";
}
} else {
throw new Error("No Token");
}
}
}
조건들을 분리하여 early return을 하면 가독성이 좋아진다.
function login(isLogin, user) {
if (isLogin) {
return;
}
if (!checkToken()) {
throw new Error("No Token");
}
if (!user.name) {
return registerUser(user);
}
refreshToken();
return "로그인 성공";
}
if(!Number.isNaN(3)){} // x
if(isNumber(3){} // o
<Switch>
를 사용하여 특정 주소에 해당하는 페이지가 없을 때 Not Found 페이지를 보여주도록 하는 것이 좋다. 괄호를 이용해 우선순위를 명시적으로 나타내주는게 좋다.
예측 가능하고 디버깅 하기 쉽도록 작성한다.
몸무게 + 신장 신장 -> 몸무게 + (신장 신장)
로그인 && 토큰 || 유저 -> (로그인 && 토큰) || 유저
number-- -> number = number - 1
??
null이거나 undefined인지 체크하고 싶을 때 : ??
falsy 체크하고 싶을 때 : ||
연산자 우선순위가 낮다.
|| 랑 ?? 는 함께 쓸 수 없다.(함께 쓰려면 괄호로 구분해야 함)
위 보다는 아래처럼 나타내는게 좋다.
if(!(A || B)){
}
if(!A && !B){
}