[모던 JavaScript 튜토리얼] 2.8 기본 연산자와 수학

모던 JavaScript 튜토리얼을 읽고 정리하였습니다.

기본 연산자와 수학

이번 파트에서는 +, -, * 와 같은 기본 연산자를 시작으로 자바스크립트에서만 제공하는 연산자에 대해 배울 것이다.


용어: ‘단항’, ‘이항’, ‘피연산자’

  • 피연산자(operand) 연산자가 연산을 수행하는 대상, 5 * 2에서 왼쪽 피연산자 5와 오른쪽 피연산자 2, 총 두 개의 피연산자가 있다. ‘피연산자’는 인수(argument)라는 용어로 불리기도 한다.

  • 단항(unary) 연산자 피연산자를 하나만 받는 연산자이며, 피연산자의 부호를 뒤집는 단항 마이너스 연산자 - 가 대표적인 예이다.

  • 이항(binary) 연산자 두 개의 피연산자를 받는 연산자는 이항(binary) 연산자라고 한다. 마이너스 연산자는 단항 연사자와 이항 연산자 두 가지 용도로 사용될 수 있다.

    let x = 1, y = 3;
    alert(y - x);
    

수학

자바스크립트에서 지원하는 수학 연산자는 다음과 같다.

  • 덧셈 연산자 +
  • 뺄셈 연산자 -
  • 곱셈 연산자 *
  • 나눗셈 연산자 /
  • 나머지 연산자 %
  • 거듭제곱 연산자 **

나머지 연산자(remainder operator) %

나머지 연산자를 사용한 표현식 a % b는 a를 b로 나눈 나머지를 정수로 반환한다.

alert(5 % 2); // 1
alert(8 % 3); // 2

거듭제곱 연산자(exponentiation operator) **

거듭제곱 연산자를 사용한 a ** b는 a를 b번 곱한 값이 반환된다.

alert(2 ** 2); // 4
alert(2 ** 3); // 8
alert(2 ** 4); // 16

거듭제곱 연산자는 정수가 아닌 숫자에 대해서도 동작한다. 1/2를 사용하면 제곱근을 구할 수 있다.

alert( 4 ** (1/2)); // 2
alert( 8 ** (1/3)); // 2

이항 연산자 ‘+’와 문자열 연결

덧셈 연산자 + 는 숫라를 더한 결과를 반환하나, 이항 연산자 +와 핀연산자로 문자열이 전달되면 덧셈 연산자는 덧셈이 아닌 문자열을 병합(연결)한다.

let s = "my" + "string";
alert(s); // mystring

이항 연산자 +를 사용할 때는 피연산자 중에서 하나라도 문자열이 존재한다면 다른 하나도 문자열로 변환되므로 결과 값은 문자열이다.

alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"

연산은 왼쪽에서 오른쪽으로 순차적으로 진행되기 때문에 여러 개의 숫자 피연산자들 뒤에 문자열 피연산자가 올 때에는 숫자가 먼저 더해진 후 더해진 숫자와 문자열을 병합한다.

alert( 2 + 2 + '1'); // "41"

오직 +이 문자열 연결이라는 기능을 제공하며, 이외의 다른 연산자들은 수학 연산자 외에 다른 기능을 수행하지 않는다.

alert( 6 - '2'); // 4
alert('6' / '2'); // 3

단항 연산자 +와 숫자형으로의 변환

덧셈 연산자 +는 이항 연산자 뿐만 아니라 단항 연산자로도 사용될 수 있다. 숫자에 단항 덧셈 연산자를 붙이면 이 연산자는 아무런 동작도 하지 않지만 피연산자가 숫자가 아닌 경우엔 숫자형으로의 변환이 일어난다. 즉 Number() 함수보다 간결하게 동일한 역할을 수행할 수 있다는 것이다.

let x = 1;
alert( +x ); // 1

let y = -2;
alert ( +y ); // -2

alert( +true ); // 1
alert( +"" ); // 0

사용자에게서 입력받아온 각각의 문자열들을 숫자로 바꾼 뒤 + 덧셈 연산을 하고자 한다면 다음과 같이 단항 연산자 +를 사용해서 간결하게 연산을 할 수가 있다.

let apples = "2";
let oranges = "3";
alert( apples + oranges ); // "23", 문자열이 연결된다.

let apples = "2";
let oranges = "3";
alert( +apples + +oranges ); // 5
// alert( Number(apples) + Number(oranges) ); // 5

연산자 우선순위

하나의 표현식에 둘 이상의 연산자가 있는 경우, 실행 순서는 연산자의 우선순위(precedence)에 의해 결정된다. 대표적인 연산자들의 우선순위는 다음과 같다.

순위 연산자 이름 기호
17 단항 덧셈 +
17 단항 부정 -
16 지수 **
15 곱셈 *
15 나눗셈 /
13 덧셈 +
13 뺄셈 -
3 할당 =

단항 덧셈 연산자는 이항 연산자보다 우선순위가 높기 때문에 단항 ‘‘+apples + +oranges”의 결과가 숫자인 것이다.


할당 연산자

무언가를 변수에 할당할 때 사용되는 = 은 할당(assignment) 연산자이다. 우선순위는 3으로 아주 낮다.

 let x = 2 * 2 + 1;
 alert(x); // 5

### 값을 반환하는 할당 연산자

=도 연산자이므로 값을 반환한다. x = value를 호출하면 value가 x에 쓰여지는 동시에 value가 반환된다.

let a = 1;
let b = 2;
let c = 3 - (a = b + 1);

alert(a); // 3
alert(c); // 0

세번째 줄에서 a에 b + 1인 3을 할당하고 괄호 안의 연산이 a의 값인 3을 반환하므로, 이어서 3 - 3이 계산되어 c에 0이 할당된다. 그러나 코드를 작성할 때에는 이런 방식으로 연산자를 사용하는 것은 가독성을 떨어르티고 코드가 명확하지 않기 때문에 권장되지 않는다.

할당 연산자 체이닝

할당 연산자는 아래와 같이 여러개를 연결할 수도 있다. 할당 연산자를 여러 개 연결하면 평가는 우측부터 진행된다. 즉, 2 + 2 가 가장 먼저 평가되고, 이 결과가 우측에서부터 c, b, a에 순차적으로 할당된다. 따라서 모든 변수가 단일 값을 공유한다.

let a, b, c;
a = b = c = 2 + 2;

alert(a); // 4
alert(b); // 4
alert(c); // 4

그렇지만 되도록이면 가독성을 위해 아래와 같이 줄을 나눠 코드를 작성하길 권장한다.

c = 2 + 2;
b = c;
a = c;

복합 할당 연산자

프로그램을 짜다 보면, 변수에 연산자를 적용하고 그 결과를 같은 변수에 저장해야 하는 경우가 생긴다. 이 때, +=와 *= 연산자를 사용하면 짧은 문법으로 동일한 연산을 수행한다.

let n = 2;
n = n + 5;
n = n * 2;

n = 2;
n += 5; // n = 5 + 2;
n *= 2; // n = 2 * 7;

alert(n); // 14

이러한 복합 할당 연산자는 산술 연산자와 비트 연산자에도 적용이 가능하다. /=, -=. 등의 연산자를 만들 수 있다. 복합 할당 연산자의 우선순위는 할당 연산자와 동일하므로 대부분의 연산자가 모두 실행된 후 실해된다.

 let n = 2;
 n *= 3 + 5;
 alert(n) // 16

증가·감소 연산자

숫자를 하나 늘리거나 줄이는 연산을 해주는 연산자를 제공한다.

  • 증가(increment) 연산자 ++는 변수를 1 증가시킨다.

    let counter = 2;
    counter++;
    alert(counter); // 3
    
  • 감소(decrement) 연산자 –는 변수를 1 감소시킨다.

    let counter = 2;
    counter--;
    alert(counter); // 1
    

증가/감소 연산자는 변수에만 쓸 수 있으므로 5++처럼 값에 사용하면 에러가 발생한다.

++와 – 연산자는 변수 앞이나 뒤에 올 수 있다.

  • 후위형(postfix form) : 피연산자 뒤
  • 전위형(prefix form) : 피연산자 앞

두 형의 차이는 반환 값을 사용할 때 드러난다. 전위형이 반환하는 값은 1을 증가시킨 값이므로 a에는 2가 쓰여진다.

let counter = 1;
let a = ++counter; 

alert(a) // 2

그러나 후위형은 피연산자에 대해 1을 더하긴 하지만 그 자체가 반환하는 값은 1을 증가시키기 전 값이므로 a에는 1이 쓰여진다.

let counter = 1;
let a = counter++;

alert(a); // 1

증가/감소 연산자의 우선순위는 다른 대부분의 산술 연산자보다 높기 때문에, 평가가 먼저 이뤄진다.

let counter = 1;
alert( 2 * ++counter); // 4

그러나 이렇게 코드를 작성하는 것도 가독성을 떨어트리기 때문에 왠만하면 ‘코드 한 줄엔, 동작 하나’에 관련된 내용만 작성하는 것이 좋다.


비트 연산자

비트 연산자(bitwise operator)는 인수를 32비트 정수로 변환하여 이진 연산을 수행한다.

  • 비트 AND ( & )
  • 비트 OR ( | )
  • 비트 XOR ( ^ )
  • 비트 NOT ( ~ )
  • 왼쪽 시프트(LEFT SHIFT) ( << )
  • 오른쪽 시프트(RIGHT SHIFT) ( >> )
  • 부호 없는 오른쪽 시프트(ZERO-FILL RIGHT SHIFT) ( >>> )

쉼표 연산자

쉼표 연산자(comma operator) , 는 여러 표현식을 코드 한 줄에서 평가할 수 있게 한다. 이때 표현식 각각이 모두 평가되지만, 마지막 표현식의 평가 결과만 반환된다는 점에 유의해야 한다.

let a = (1 + 2, 3 + 4);
alert(a); // 7

쉼표 연산자의 우선순위는 매우 낮으며, =보다도 낮다.

이 쉼표 연산자는 여러 동작을 하나의 줄에서 처리하려는 복잡한 구조에서 사용된다.

for (a = 1, b = 3, c = a * b; a < 10; a++) {
...
}

쉼표 연산자를 사용한 트릭은 자바스크립트 프레임워크에서 자주 볼 수 있으므로 알아두는 것이 좋다. 그러나 코드 가독성에는 좋지 않기 때문에 꼭 필요한 경우에만 사용하는 것이 좋다.

Comments