Posts 모던 자바스크립트 #2.8. 기본 연산자와 수학
Post
Cancel

모던 자바스크립트 #2.8. 기본 연산자와 수학

모던 JavaScript 튜토리얼을 따라가면서 정리합니다.

2.8. 기본 연산자와 수학

단항, 이항,. 피연산자

  • 피연산자(operand; 인수(argument)): 연산자가 연산을 수행하는 대상.
  • 단항(unary) 연산자: 피연산자를 하나만 받는 연산자
  • 이항(binary) 연산자: 두 개의 피연산자를 받는 연산자

거듭제곱 연산자 **

거듭제곱 연산자(exponentiation operator)를 사용한 a ** b를 평가하면 ab번 곱한 값이 반환된다. 정수가 아닌 숫자에 대해서도 동작한다. 1/2를 사용하면 제곱근을 구할 수 있다.

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

이항 연산자 +피연산자 중 어느 하나로 문자열이 전달되면 덧셈 연산자는 덧셈이 아닌 문자열을 병합(연결)한다. 이때 순서는 중요하지 않다.

1
alert(2 + 2 + '1'); // '221'이 아니라 '41'이 출력된다. 

연산은 왼쪽에서 오른쪽으로 순차적으로 진행된다. 두 개의 숫자 뒤에 문자열이 오는 경우, 숫자가 먼저 더해지고, 그 후 더해진 숫자와 문자열과의 병합이 일어난다. 이처럼 다른 산술 연산자가 오직 숫자형의 피연산자만 다루고, 피연산자가 숫자형이 아닌 경우에 그 형을 숫자형으로 바꾸는 것과는 대조적이다.

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

숫자에 단항 덧셈 연산자를 붙이면 이 연산자는 아무런 동작도 하지 않는다. 그러나 피연산자가 **숫자가 아닌 경우에는 Number(value)와 같이 숫자형으로의 변환이 일어난다. **

1
2
3
4
5
let y = -2;
alert(+y); //-2

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

개발을 하다 보면 문자열을 숫자로 변환해야 하는 경우가 자주 생긴다. HTML 폼(form) 필드에서 값을 가져왔는데 그 값이 문자형일 때가 그 예시다. 실제로 폼에서 가지고 온 값은 대개 문자열 형태이다.

이항 덧셈 연산자를 사용하면 아래와 같이 값이 문자열로 변해서 연결될 것이다.

1
2
3
4
let apples = "2";
let oranges = "3";

alert( apples + oranges ); // 23, 이항 덧셈 연산자는 문자열을 연결한다.

원하는 대로 값을 더해주려면, 단항 덧셈 연산자를 사용해 피연산자를 숫자형으로 변화시키면 된다.

1
2
3
4
5
6
7
8
let apples = "2";
let oranges = "3";

// 이항 덧셈 연산자가 적용되기 전에, 두 피연산자는 숫자형으로 변화한다.
alert( +apples + +oranges ); // 5

// `Number(...)`를 사용해서 같은 동작을 하는 코드를 작성할 수 있다.
// alert( Number(apples) + Number(oranges) ); // 5

연산자 우선순위

하나의 표현식에 둘 이상의 연산자가 있는 경우, 실행 순서는 연산자의 우선순위(precedence) 에 의해 결정된다. 한편 괄호는 모든 연산자보다 우선순위가 높기 때문에 우선순위를 변경하려면 괄호를 사용하면 된다. 우선순위가 같으면 왼쪽에서 오른쪽으로 연산이 수행된다. 동일한 기호의 단항 연산자는 이항 연산자보다 우선순위가 더 높다.

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

할당 연산자

무언가를 할당할 때 쓰이는 =는 할당(assignment) 연산자라고 불리는데, 우선순위는 3으로 아주 낮다.

값을 반환하는 할당 연산자

자바스크립트에서 대부분의 연산자들은 값을 반환한다. =도 마찬가지이다. x = value을 호출하면 valuex에 쓰여지고, 이에 더하여 value가 반환된다.

1
2
3
4
5
6
7
let a = 1;
let b = 2;

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

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

위 예제에서 표현식 (a = b + 1)a에 값을 할당하고, 그 값인 3을 반환한다. 그리고 반환 값은 이어지는 표현식에 사용된다. 가독성이 떨어지기 때문에 사용하지 않는 것이 좋다.

할당 연산자 체이닝

할당 연산자는 아래와 같이 여러 개를 연결할 수도 있다.

1
2
3
4
5
6
7
let a, b, c;

a = b = c = 2 + 2;

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

이렇게 할당 연산자를 여러 개 연결한 경우, 평가는 우측부터 진행된다. 먼저 가장 우측의 2 + 2가 평가되고, 그 결과가 좌측의 c, b, a에 순차적으로 할당된다. 그러나 가독성을 위해 연산자를 체이닝하지 말고 줄을 나눠 코드를 작성하자.

복합 할당 연산자

짧은 문법으로 변수에 연산자를 적용하고 그 결과를 같은 변수에 저장해야 할 때 사용한다.

1
2
3
4
5
let n = 2;
n += 5; // n은 7이 됩니다(n = n + 5와 동일).
n *= 2; // n은 14가 됩니다(n = n * 2와 동일).

alert( n ); // 14

복합 할당 연산자의 우선순위는 할당 연산자와 동일하다. 대부분 다른 연산자가 실행된 후에 복합 할당 연산자가 실행된다.

증가·감소 연산자

증가/감소 연산자는 변수에만 쓸 수 있다. 값에 사용하려고 하면 에러가 발생한다.

전위형과 후위형

  • 후위형 증가/감소 연산자(postfix form): 증가/감소 후의 새로운 값을 반환한다.
  • 전위형 증가/감소 연산자(prefix form): 증가/감소 전의 기존 값을 반환한다.

모든 연산자는 값을 반환한다.

  • 1) 반환 값을 사용하지 않는 경우라면, 전위형과 후위형엔 차이가 없다.

    1
    2
    3
    4
    
    let counter = 0;
    counter++;
    ++counter;
    alert( counter ); // 2, 위 두 라인은 동일한 연산을 수행한다.
    
  • 2) 값을 증가시키고 난 후, 증가한 값을 바로 사용하려면 전위형 증가 연산자를 사용하면 된다.

    1
    2
    
    let counter = 0;
    alert( ++counter ); // 1
    
  • 3) 값을 증가시키지만, 증가 전의 기존값을 사용하려면 후위형 증가 연산자를 사용하면 된다.

    1
    2
    
    let counter = 0;
    alert( counter++ ); // 0
    

다른 연산자 사이의 증가/감소 연산자

++/-- 연산자를 표현식 중간에 사용하는 것도 가능하다. 이때, 증가/감소 연산자의 우선순위는 다른 대부분의 산술 연산자보다 높기 때문에, 평가가 먼저 이뤄진다.

1
2
3
4
5
6
7
let counter = 1;
// 전위
alert( 2 * ++counter ); // 4

// 후위
counter = 1;
alert( 2 * counter++ ); // counter++는 '기존'값을 반환하기 때문에 2가 출력된다.

위 코드는 한 줄에서 여러 가지 일을 동시에 하고 있기 때문에 코드의 가독성이 떨어진다. 코드를 읽을 때 눈을 ‘수직으로’ 빠르게 움직이다 보면 counter++와 같은 것을 놓치기 쉽다. 변수가 증가했다는 것을 놓칠 수 있는 것이다. 따라서 코드 한 줄엔, 특정 동작 하나에 관련된 내용만 작성하는 게 좋다.

1
2
3
let counter = 1;
alert( 2 * counter );
counter++;

비트 연산자(bitwise operator)

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

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

비트 연산자는 저수준(2진 표현)에서 숫자를 다뤄야 할 때 쓰이므로 웹 개발 시에는 만날 일이 거의 없다.

쉼표 연산자(comma operator)

좀처럼 보기 힘들고, 특이한 연산자 중 하나이다. 코드를 짧게 쓰려는 의도로 가끔 사용된다. 쉼표 연산자 ,는 여러 표현식을 코드 한 줄에서 평가할 수 있게 해준다. 이때 표현식 각각이 모두 평가되지만, 마지막 표현식의 평가 결과만 반환되는 점에 유의해야 한다.

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

alert( 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를 연산한 것처럼 될 것이다.

이렇게 마지막 표현식을 제외한 모든 것을 버리는 연산자는 여러 동작을 하나의 줄에서 처리하려는 복잡한 구조에서 사용한다.

1
2
3
4
// 한 줄에서 세 개의 연산이 수행됨
for (a = 1, b = 3, c = a * b; a < 10; a++) {
 ...
}

쉼표 연산자는 코드 가독성에 도움이 되지 않기 때문에, 진짜 필요한 경우에만 사용해야 한다.

과제

Q1. 아래 코드가 실행된 후, 변수 a, b, c, d엔 각각 어떤 값들이 저장될까요?

1
2
3
4
let a = 1, b = 1;

let c = ++a; // 2: 증가 후의 값을 리턴 
let d = b++; // 1: 증가 전의 값을 리턴

Q2. 아래 코드가 실행되고 난 후, ax엔 각각 어떤 값이 저장될까요?

1
2
3
4
5
let a = 2;

let x = 1 + (a *= 2); 
// x: 5
// a: 4

Q3. 아래 표현식의 결과 예측

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"" + 1 + 0    //10
"" - 1 + 0    //-1
true + false  //1
6 / "3"       //2
"2" * "3"     //6
4 + 5 + "px"  //9px
"$" + 4 + 5   //$45
"4" - 2       //2
"4px" - 2     //NaN
7 / 0         //Infinity
"  -9  " + 5  //  -9  5
"  -9  " - 5  //-14
null + 1      //1: 숫자형으로 변환시 null은 0이 된다.
undefined + 1 //NaN: 숫자형으로 변환시 undefined는 NaN이 된다.
" \t \n" - 2
//" \t \n"는 숫자형으로 변환 시 길이가 0인 문자열로 취급되어 숫자 0이 된다.

Q4. 예시가 제대로 동작하도록 코드를 수정해 보세요. 결과는 3이 되어야 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let a = prompt("덧셈할 첫 번째 숫자를 입력해주세요.", 1);
let b = prompt("덧셈할 두 번째 숫자를 입력해주세요.", 2);

alert(a + b); // 12

//해답
alert(+a + +b);
// Prompt의 리턴값은 문자열이다.
// 이항덧셈연산자는 문자열을 더하였을 때 문자열을 열결해서 반환한다.
// 이항덧셈연산자가 더하기 전에 각 문자열을 숫자로 바꾸어야 한다.
// 단항덧셈연산자는 숫자에 붙었을 때는 아무 일도 안하지만 문자에 붙었을 때는 숫자를 리턴한다.
// 즉 Number(a)와 a++는 같다.
// 1)
// alert(+a + +b);
// 2)
// let a = +prompt("덧셈할 첫 번째 숫자를 입력해주세요.", 1);
// let b = +prompt("덧셈할 두 번째 숫자를 입력해주세요.", 1);
This post is licensed under CC BY 4.0 by the author.

모던 자바스크립트 #2.7. 형 변환

모던 자바스크립트 #2.9. 비교 연산자

Loading comments from Disqus ...