연산자 우선순위
자바스크립트에서 &&
, ||
연산자는 단순히 true/false를 반환하는게 아니라, 독특하게도 피연산자 중 하나를 선택하여 반환한다. 그나마 피연산자가 2개뿐이고 연산자가 하나밖에 없을 경우는 결괏값을 쉽게 예상할 수 있다. 하지만 연산자가 2개, 3개 이상이라면?
var a = 42;
var b = "foo";
var c = [1, 2, 3];
a && b || c;
a || b && c;
두 표현식의 결과를 이해하려면 표현식에 연산자가 여러 개 있을 경우 어떤 규칙으로 처리되는 지 알아야 한다.
바로 이 규칙을 '연산자 우선순위'라고 한다.
앞에서 한번 봤던 예제다.
var a = 42,
b;
b = (a++, a);
a; // 43
b; // 43
()를 없애면 어떻게 될까? b는 42가 된다. 갑자기 왜 바뀌었을까? 이유는 , 연산자가 = 연산자보다 우선순위가 낮기 때문이다. 그러므로 b = a++ , a
를 엔인은 (b = a++, a)
로 해석한다. a++는 ++ 연산자가 a값을 변경하는 부수효과를 일으키기 전에 b에 42를 할당한다.
연산자 우선순위를 왜 알아야 하는지 좋은 참고가 되었으리라 본다. 다수의 문을 연결하는 연산자로 , 를 사용할 때에는 이션산자의 우선순위가 최하위라는 사실 또한 반드시 알고 있어야 한다.
이번에는 좀 더 복잡한 예제를 보자.
var a = 42;
var b = "foo";
var c = false;
var d = a && b || c ? c || b ? a : c && b : a;
d; // ?
정말 나쁜 코드다. 이렇게 오른쪽으로 길게 늘어진 표현식을 쓰고 싶을 사람이 있나? 가능성은 낮지만, 이 코드를 보면서 다수의 연산자를 연산자 체이닝할 경우의 이슈를 보자.
결과 부터 말하면 42다. 그러나 이코드를 자바스크립트 에닞ㄴ에 꽂아 정렬도 시켜보지 않고 답이 뭘까 궁리하는건 의미가 없자.
첫째 질문은 '제일 앞의 (a && b || c)
가 (a && b) || c
와 a && (b || c)
중 어느쪽으로 해석될까?'이다 답을 알겠는가? 적어도 이 둘이 완전히 다른 연산이란 정도는 마음속으로 느낄 것이다.
(false && true) || true; // true
false && (true || true); // false
&& 연산자가 먼저 평가되고 || 연산자가 그다음에 평가된다. 처리방향이 촤즉 -> 우측 순서여서가 아니다.
모든 프로그래밍 언어에는 연사낮 우선순위 리스트가 있따. 자바스크립트는 연산자 우선순위 리스트를 자바스크립트 개발자가 자세히 읽어보는 일 자체가 드물다
&&가 || 보다 우선하여 처리된다는걸 잘 알고 있는사람이라면, 함정에 빠질 일은 ㅇ벗다. 하지만 장담컨데 꽤많은 사람들이 골똘히 생각했을 것이다.
아쉽게도 자바스크립트 명세서에는 하눈ㄴ에 알아보기 쉽게 잘 정리된 연산자 우선순위 리스트가 없으므로 스스로 분석해보고 문법 규칙을 이해해야 한다. 그래서 언젠가 자주 쓰는 유용한 항목들을 절리해야 한다.
단락 평가
&& || 여산자는 좌측 피연산자의 평가 결과만으로 전체 결과가 이미 결정될 경우 우측 피연산자의 평가를 건너뛴다. 그래서 '단락'이란 말이 유래된 것이다.
예를 들어 a && b
에서 a가 falsy면 b는 쳐다보지도 않는다. && 연산 결과가 이미 false로 굳어진 마당에 애써 b르 조사할 필요가 없다. 마찬가지로 a || b
에서 a가 truthy면, 이미 전체 결괏값은 true로 확정되므로 b는 관심을 둘 이유가 없다.
단락 평가는 아주 유용하고 자주 쓰인다.
function doSomething(opts) {
if (opts && opts.cool) {
// ..
}
}
opts && opts.cool
에서 opts는 일종의 가드다 만약 opts가 존재하지 않는다면 당연히 opts.cool 표현식은 에러일 수 밖에 없다. 일단 opts를 먼저 단락 평가해보고, 그 결과가 실패면 opts.cool은 자동으로 건너뛰니 결과적으로 에러는 나지 않는다.
끈근한 우정
다음은 앞에서 예시했던 연산자 뭉치가 죽 연결된, 복잡한 문이다. 삼항 연산자 ? :
부분을 잘보기 바란다. ? :
는 &&
와 ||
보다 우선순위가 높을까 아니면 낮을까?
a && b || c ? c || b ? a : c && b : a;
즉, 다음 둘 중에서 어느 쪽으로 처리될까?
a && b || (c ? c || (b ? a : c) && b) : a);
(a && b || c) ? (c || b) ? a : (c && b) : a;
둘중 정답은 아래다. && 는 || 보다, ||는 ? : 보다 우선순위가 높기 때문이다.
따라서 표현식 (a && b || c)
가 ? :
보다 먼저 평가된다.
참고
- You Don't Know JS - 타입과 문법, 스코프와 클로저( 한빛 미디어 )
'JAVASCRIPT' 카테고리의 다른 글
[JS][스코프] 스코프란? (0) | 2022.02.15 |
---|---|
[JS][문법] Switch (0) | 2022.02.14 |
[JS][문법] 콘텍스트 규칙 (0) | 2022.02.14 |
[JS][문법] 표현식의 부수 효과 (0) | 2022.02.13 |
[JS][문법] 문과 표현식 (0) | 2022.02.13 |
댓글