연산자는 덧셈, 뺄셈, 곱셈 등을 수행하게 하는 문자이다. (+, -, *, /)
이러한 기본연산자 외에도 자바스크립트에서 제공하는 연산자도 존재한다.
연산자가 연산을 수행하는 대상.
5 * 2에는 왼쪽 피연산자 5와 오른쪽 피연산자 2, 총 두 개의 피연산자.
인수(argument)라는 용어로 불리기도 함.
피연산자를 하나만 받는 연산자.
대표적인 예로 피연산자의 부호를 뒤집는 단항 마이너스 연산자 (-)가 있다.
let x = 1;
x = -x;
alert( x ); // -1
두 개의 피연산자를 받는 연산자.
마이너스 연산자는 아래와 같이 이항 연산자로 쓸 수도 있다.
let x = 1, y = 3;
alert( y - x ); // 2, 이항 마이너스 연산자는 뺄셈 기능
위와 같이 부호를 반전해주는 단항 마이너스 연산자와 뺄셈에 쓰이는 이항 마이너스 연산자(뺄셈 연산자)는 기호는 같지만 수행하는 연산이 다르다.
두 연산을 구분하는 기준은 피연산자의 개수이다.
자바스크립트에서 지원하는 수학 연산자.
덧셈 연산자 +
뺄셈 연산자 -
곱셈 연산자 *
나눗셈 연산자 /
나머지 연산자 %
거듭제곱 연산자 **
앞쪽 네 연산자는 일반적인 사칙연산을 수행한다.
%와 ** 또한 수학에서 일반적인 개념이지만 표현방식이 다르다.
나머지 연산자(remainder operator) %
: a % b의 경우 a를 b로 나눈 나머지를 정수로 반환
alert( 5 % 2 ); // 5를 2로 나눈 후의 나머지인 1을 출력
alert( 8 % 3 ); // 8을 3으로 나눈 후의 나머지인 2를 출력
거듭제곱 연산자(exponentiation operator) **
: a ** b의 경우 a를 b번 곱한 값을 반환.
alert( 2 ** 2 ); // 4 (2 * 2)
alert( 2 ** 3 ); // 8 (2 * 2 * 2)
alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2)
alert( 8 ** (1/3) ); // 2 (1/3 거듭제곱은 세제곱근)
덧셈 연산자 +의 피연산자.
문자열이 전달되면 덧셈 연산자는 덧셈이 아닌 문자열을 병합(연결)한다.
let s = "my" + "string";
alert(s); // mystring
이 때, 피연산자 중 하나가 문자열이면 다른 하나도 문자열로 변환된다.
alert( '1' + 2 ); // "12"
alert(2 + 2 + '1' ); // 연산은 왼쪽에서 오른쪽으로 진행되기 때문에 '221'이 아니라 '41'이 출력
문자열 연결 기능은 +의 특별한 기능이다.
-, *, / 연산자의 피연산자로 문자열이 들어오면 +처럼 숫자를 문자로 변환하는 것이 아닌 문자를 숫자로 변환하여 연산을 수행한다.
alert( 6 - '2' );
// 4, '2'를 숫자로 바꾼 후 연산
alert( '6' / '2' ); // 3, 두 피연산자가 숫자로 바뀐 후 연산
덧셈 연산자 +는 단항연산자로도 사용 가능하다.
피연산자가 숫자인 경우 단항연산자 +는 아무 동작을 하지 않지만 피연산자가 숫자가 아닌 경우 피연산자를 숫자형으로 변환한다.
// 숫자에는 아무런 영향을 미치지 않는다.
let x = 1;
alert( +x ); // 1
let y = -2;
alert( +y ); // -2
// 숫자형이 아닌 피연산자는 숫자형으로 변환한다.
alert( +true ); // 1
alert( +"" ); // 0
짧은 문법으로도 Number(...)와 동일한 일을 할 수 있게 해주는 셈이다.
let apples = "2";
let oranges = "3";
alert( apples + oranges ); // 23
alert( +apples + +oranges ); // 5
위 예제의 마지막 alert()의 인자엔 연산자 +가 세 번 포함된다. 그런데 어떻게 단항연산자 +부터 적용되어 숫자로 변환되고 그 이후에 이항연산자 +가 덧셈을 수행하는 걸까? 연산자 우선순위 때문이다.
하나의 표현식에 둘 이상의 연산자가 있는 경우, 실행 순서는 연산자의 우선순위(precedence)에 의해 결정된다. 사칙연산에서 곱셈과 나눗셈이 덧셈과 뺄셈보다 먼저 수행된다는 것이 대표적인 예이다. 곱셈, 나눗셈이 덧셈, 뺄셈보다 높은 우선순위를 갖기 때문이다.
이 우선순위에 의한 연산 순서를 조정하는 것이 괄호이다. 괄호는 모든 연산자보다 우선순위가 높기 때문에 연산 순서를 의도적으로 조정할 수 있다.
아래는 우선순위 테이블의 일부이다.(출처)
값을 변수에 할당할 때 사용하는 연산자 (=)
우선순위가 3으로 아주 낮은 편이기 때문에 할당 전에 모든 계산을 거치고 계산된 값이 변수 등에 할당되는 것이다.
값을 반환하는 연산자
단순히 할당의 기능만 수행하는 것이 아니라 타 연산자처럼 반환의 기능 또한 가지고 있다.
let a = 1;
let b = 2;
let c = 3 - (a = b + 1);
alert( a ); // 3
alert( c ); // 0
하지만 코드가 명확하지 않고 가독성이 떨어지기 때문에 권장되지 않는 방법이다.
할당 연산자 체이닝
let a, b, c;
a = b = c = 2 + 2;
alert( a ); // 4
alert( b ); // 4
alert( c ); // 4
할당 연산자 여러 개를 연결하여 사용할 수도 있으나 마찬가지로 권장되지 않는다.
변수에 연산자를 적용한 결과를 같은 변수에 저장할 때 복합 할당 연산자 +=, *= 등을 사용하여 코드 길이를 줄일 수 있다. 우선순위는 할당 연산자와 같으므로 다른 연산자 실행 후에 할당된다.
let n = 2;
n = n + 5;
n = n * 2;
let n = 2;
n += 5; // n은 7이 된다(n = n + 5와 동일).
n *= 2; // n은 14가 된다(n = n * 2와 동일)
alert( n ); // 14
변수의 숫자를 1만큼 증가 또는 감소시키는 연산자(++, --). 전위형과 후위형이 있다.
반환값이 없는 경우에는 전위형과 후위형에 차이가 없지만
반환값이 있는 경우
전위형은 반환 전 연산을 진행하여 연산 처리된 값을 반환하고
후위형은 기존의 값을 반환 후 연산을 진행한다.
let counter = 2;
alert( counter++ ); // 2
let counter = 2;
alert( --counter ); // 1
증가•감소 연산자는 다른 연산자와 함께 사용 가능하지만 코드의 가독성이 떨어지기 때문에 구분해서 사용하는 편이 좋다.
let counter = 1;
alert( 2 * counter++ ); // 가독성 떨어지는 편
let counter = 1;
alert( 2 * counter );
counter++; // 가독성 좋은 편
인수를 32비트 정수로 변환하여 이진 연산을 수행.
주로 저수준(2진 표현)에서 숫자를 다뤄야 할 때 쓰이므로 흔하게 쓰이진 않지만 암호를 다룰 때 유용하게 쓰인다.
여러 표현식을 한 줄의 코드로 평가할 수 있게 하는 연산자(,)
표현식 각각이 모두 평가되지만, 마지막 표현식의 평가 결과만 반환된다.
let a = (1 + 2, 3 + 4);
alert( a ); // 7 (3 + 4의 결과)
쉼표 연산자는 우선순위가 할당 연산자(=)보다 낮으므로 대부분의 다른 연산이 처리된 후 진행된다.
대표적인 사용 예시로 for문의 조건부가 있다.
// 한 줄에서 세 개의 연산이 수행됨
for (a = 1, b = 3, c = a * b; a < 10; a++) {
...
}
일반적으로 사용하지만 전부 우선순위에 따라 처리되기 때문에 정해진 결과가 나오는 것이다. '컴퓨터는 거짓말을 하지 않는다.'