하나의 표현식에 둘 이상의 연산자가 있는 경우, 실행 순서는 연산자의 우선순위(precedence)에 의해 결정됩니다. 우선순위를 모두 외우기보다는 필요할 때마다 참조하는 것이 좋습니다.
참고: MDN - 우선순위 테이블
+
, -
, *
, /
, %
8 ** (1/3); // 2 (1/3 거듭제곱은 세제곱근)
이항 덧셈 연산자
+
는 문자열 연결과 변환이라는 특별한 기능을 제공합니다. 다른 산술 연산자가 오직 숫자형의 피연산자만 다루고, 피연산자가 숫자형이 아니면 그 형을 숫자형으로 바꾸는 것과는 대조적입니다.// '+' 의 문자열 연결 "my" + "string"; // mystring '1' + 2; // "12" 2 + '1'; // "21" 2 + 2 + '1'; // '221'이 아니라 '41'이 출력됩니다. // 다른 산술 연산자(-, /) 6 - '2'; // 4, '2'를 숫자로 바꾼 후 연산이 진행됩니다. '6' / '2'; // 3, 두 피연산자가 숫자로 바뀐 후 연산이 진행됩니다.
덧셈 연산자
+
는 이항 연산자뿐만 아니라 단항 연산자로도 사용할 수 있습니다.
숫자에 단항 덧셈 연산자를 붙이면 이 연산자는 아무런 동작도 하지 않습니다. 그러나 피연산자가 숫자가 아닌 경우엔 숫자형으로의 변환이 일어납니다.// 숫자에는 아무런 영향을 미치지 않습니다. let x = 1; +x; // 1 // 숫자형이 아닌 피연산자는 숫자형으로 변화합니다. alert( +true ); // 1 alert( +"" ); // 0
단항 덧셈 연산자는 짧은 문법으로도 Number(...)와 같은 일을 할 수 있게 해줍니다.
let apples = "2"; let oranges = "3"; // 이항 덧셈 연산자가 적용되기 전에, 두 피연산자는 숫자형으로 변화합니다. alert( +apples + +oranges ); // 5 // `Number(...)`를 사용해서 같은 동작을 하는 코드를 작성할 수 있지만, 더 기네요. // alert( Number(apples) + Number(oranges) ); // 5
무언가를 할당할 때 쓰이는
=
도 연산자입니다. 이 연산자는할당(assignment) 연산자
라고 불리는데, 우선순위는 3으로 아주 낮습니다.
=
는 연산자이기 때문에 흥미로운 함축성을 내포하고 있습니다. 자바스크립트에서 대부분의 연산자는 값을 반환합니다.+
와-
뿐만 아니라=
역시 값을 반환하죠.
x = value
을 호출하면value
가x
에 쓰이고, 이에 더하여value
가 반환됩니다.
할당 연산자
는 여러 개를 연결할 수도 있습니다(체이닝).a = b = c = 2 + 2;
이렇게 할당 연산자를 여러 개 연결한 경우, 평가는 우측부터 진행됩니다. 먼저 가장 우측의2 + 2
가 평가되고, 그 결과가 좌측의c
,b
,a
에 순차적으로 할당됩니다. 모든 변수가 단일 값을 공유하게 되죠.
그런데 되도록 연산자를 체이닝 하는 것 보다 가독성을 위해 아래와 같이 줄을 나눠 코드를 작성하길 권유 드립니다.
+=
, *=
, /=
, -=
++
, --
(전위형
/ 후위형
)
- 증가/감소 연산자는 변수에만 쓸 수 있습니다.
5++
와 같이 값에 사용하려고 하면 에러가 발생합니다.- 전위형은 증가/감소 후의 새로운 값을 반환하는 반면, 후위형은 증가/감소 전의 기존 값을 반환합니다.
++
/--
연산자를 표현식 중간에 사용하는 것도 가능합니다. 이때, 증가/감소 연산자의 우선순위는 다른 대부분의 산술 연산자보다 높기 때문에, 평가가 먼저 이뤄집니다. (하지만 한 줄에서 여러 가지 일을 동시에 하고 있기 때문에 코드의 가독성이 떨어집니다.)
참고: MDN - 비트 연산자
쉼표 연산자 ,
는 여러 표현식을 코드 한 줄에서 평가할 수 있게 해줍니다. 이때 표현식 각각이 모두 평가되지만, 마지막 표현식의 평가 결과만 반환되는 점에 유의해야 합니다.
let a = (1 + 2, 3 + 4); a; // 7 (3 + 4의 결과)
첫 번째 표현식
1 + 2
은 평가가 되지만 그 결과는 버려집니다.3 + 4
만 평가되어a
에 할당되죠.
쉼표 연산자
의 연산자 우선순위는 매우 낮습니다.할당 연산자 =
보다 더 낮죠. 따라서 위 예시에선 괄호가 중요한 역할을 합니다.
괄호가 없으면a = 1 + 2, 3 + 4
에서+
가 먼저 수행되어a = 3, 7
이 됩니다. 할당 연산자 =는 쉼표 연산자보다 우선순위가 높기 때문에a = 3
이 먼저 실행되고, 나머지(7
)는 무시되죠.(a = 1 + 2), 3 + 4
를 연산한 것처럼 될 겁니다.
이렇게 마지막 표현식을 제외한 모든 것을 버리는 연산자는 여러 동작을 하나의 줄에서 처리하려는 복잡한 구조에서 이를 사용합니다.
// 한 줄에서 세 개의 연산이 수행된다. for (a = 1, b = 3, c = a * b; a < 10; a++) { ... }
쉼표 연산자를 사용한 트릭은 여러 자바스크립트 프레임워크에서 볼 수 있습니다. 쉼표 연산자 또한 코드 가독성에 도움이 되지 않습니다.
>
, <
, >=
, <=
, ==
, !=
, ===
, !==
다른 연산자와 마찬가지로 비교 연산자 역시 값을 반환합니다. 반환 값은 불린형입니다. 반환된 불린값은 다른 여타 값처럼 변수에 할당 할 수 있습니다.
자바스크립트는 '사전’ 순으로 문자열을 비교합니다. 실제 단어를 사전에 실을 때 단어를 구성하는 문자 하나하나를 비교하여 등재 순서를 정하는 것과 같이 자바스크립트도 문자열을 구성하는 문자 하나하나를 비교해가며 문자열을 비교합니다.
비교하려는 값의 자료형이 다르면 자바스크립트는 이 값들을 숫자형으로 바꿉니다. 불린값의 경우
true
는1
,false
는0
으로 변환된 후 비교가 이뤄집니다.'2' > 1; // true, 문자열 '2'가 숫자 2로 변환된 후 비교가 진행된다. '01' == 1; // true, 문자열 '01'이 숫자 1로 변환된 후 비교가 진행된다. true == 1; // true false == 0; // true let a = 0; alert( Boolean(a) ); // false let b = "0"; alert( Boolean(b) ); // true alert(a == b); // true!
동등 연산자(equality operator) ==
은0
과false
를 구별하지 못한다.
일치 연산자(strict equality operator) ===
를 사용하면 형 변환 없이 값을 비교할 수 있다.
산술 연산자나 기타 비교 연산자
<
,>
,<=
,>=
를 사용하여null
과undefined
를 비교할 경우null
과undefined
는 숫자형으로 변환된다.null
은0
,undefined
는NaN
으로 변한다.null === undefined; // false(두 값의 자료형이 다르기 때문에 일치 비교 시 거짓이 반환됨) null == undefined; // true
null
vs 0
null > 0; // false (null이 숫자형으로 변환돼 0이 되기 때문)
null == 0; // false (형 변환을 하지 않음)
null >= 0; // true (null이 숫자형으로 변환돼 0이 되기 때문)
// `동등 연산자 ==`는 피연산자가 `undefined`나 `null`일 때 형 변환을 하지 않는다. `undefined`와 `null`을 비교하는 경우에만 `true`를 반환하고, 그 이외의 경우(`null`이나 `undefined`를 다른 값과 비교할 때)는 무조건 `false`를 반환한다.
undefined
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
// (1)과 (2)에선 `undefined`가 `NaN`으로 변환되는데(숫자형으로의 변환), `NaN`이 피연산자면 비교 연산자는 항상 `false`를 반환한다. `undefined`는 `null`이나 `undefined`와 같고, 그 이외의 값과는 같지 않기 때문에 (3)은 `false`를 반환한다.
일치 연산자 ===
를 제외한 비교 연산자의 피연산자에undefined
나null
이 오지 않도록 특별히 주의하시기 바랍니다.- 또한,
undefined
나null
이 될 가능성이 있는 변수가>=
,>
,<
,<=
의 피연산자가 되지 않도록 주의하시기 바랍니다. 명확한 의도가 있지 않은 이상 말이죠. 만약 변수가undefined
나null
이 될 가능성이 있다고 판단되면, 이를 따로 처리하는 코드를 추가하시기 바랍니다.
- 숫자
0
, 빈 문자열""
,null
,undefined
,NaN
은 불린형으로 변환 시 모두false
가 됩니다. 이런 값들은‘falsy(거짓 같은)’ 값
이라고 부릅니다.- 이 외의 값은 불린형으로 변환시
true
가 되므로‘truthy(참 같은)’ 값
이라고 부릅니다.
조건부 연산자
는 물음표?
로 표시합니다. 피연산자가 세 개이기 때문에조건부 연산자
를'삼항(ternary) 연산자’
라고 부르는 사람도 있습니다. 참고로, 자바스크립트에서 피연산자가 3개나 받는 연산자는조건부 연산자
가 유일합니다.let result = condition ? value1 : value2; // 평가 대상인 condition이 truthy라면 value1이, 그렇지 않으면 value2가 반환된다.
let accessAllowed;
let age = prompt('나이를 입력해 주세요.', '');
if (age > 18) {
accessAllowed = true;
} else {
accessAllowed = false;
}
// '조건부 연산자’를 사용하면 위 예시를 더 짧고 간결하게 변형할 수 있다.
let accessAllowed = (age > 18) ? true : false;
// 조건문을 괄호로 감싸지 않아도 연산자 우선순위 규칙에 따라, 비교 연산 'age > 18'이 먼저 실행된다.
// 하지만 코드의 가독성 향상을 위해 괄호를 사용할 것을 권유합니다.
let age = prompt('나이를 입력해주세요.', 18);
let message = (age < 3) ? '아기야 안녕?' :
(age < 18) ? '안녕!' :
(age < 100) ? '환영합니다!' :
'나이가 아주 많으시거나, 나이가 아닌 값을 입력 하셨군요!';
// if..else를 사용하면 위 예시를 아래와 같이 변형할 수 있다.
if (age < 3) {
message = '아기야 안녕?';
} else if (age < 18) {
message = '안녕!';
} else if (age < 100) {
message = '환영합니다!';
} else {
message = '나이가 아닌 값을 입력 하셨군요!';
}
let company = prompt('자바스크립트는 어떤 회사가 만들었을까요?', '');
(company == 'Netscape') ?
alert('정답입니다!') : alert('오답입니다!');
위 예시에선 평가 결과를 변수에 할당하지 않고, 결과에 따라 실행되는 표현식이 달라지도록 하였습니다.
그런데 이런 식으로 물음표 연산자를 사용하는 것은 좋지 않습니다.
개발자 입장에선if 문
을 사용할 때 보다 코드 길이가 짧아진다는 점 때문에 물음표?
를if
대용으로 쓰는 게 매력적일 순 있습니다. 하지만 이렇게 코드를 작성하면 가독성이 떨어집니다.// 아래는 if를 사용해 변형한 코드입니다. let company = prompt('자바스크립트는 어떤 회사가 만들었을까요?', ''); if (company == 'Netscape') { alert('정답입니다!'); } else { alert('오답입니다!'); } // 코드를 읽을 때 우리의 눈은 수직으로 움직입니다. 수평으로 길게 늘어진 코드보단 여러 줄로 나뉘어 작성된 코드 블록이 더 읽기 쉽죠. 물음표 연산자 ?는 조건에 따라 반환 값을 달리하려는 목적으로 만들어졌습니다. 이런 목적에 부합하는 곳에 물음표를 사용하시길 바랍니다. 여러 분기를 만들어 처리할 때는 if를 사용하세요.
산술 연산자
와 일치 연산자
를 제외한 비교 연산자
에서 null
과 undefined
가 숫자형으로 변환되는 부분이다. 이로 인해 매우 헷갈리는 결과가 발생한다. 그러므로 명확한 의도를 갖지 않은 한 undefined
와 null
가 피연산자에 되지 않게 주의해야 한다.null
과 undefined
가 피연산자일 경우의 상황 다시 보기