2-7 연산자

bi_sz·2020년 4월 22일
1

JavaScript

목록 보기
10/22

1. 연산자

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

  • 피연산자를 하나만 받는 연산자는 단항 ( unary ) 연산자 라고 부른다.
  • 피연산자의 부호를 뒤집는 단항 마이너스 연산자 - 는 단항 연산자의 대표적인 예이다.
let x = 1;
x = -x;
alert( x );   // - 1 , 단항 마이너스 연산자는 부호를 뒤집는다.
  • 두 개의 피연산자를 받는 연산자는 이항 ( binary ) 연산자 라고 부른다.
    마이너스 연산자는 이항 연산자로 쓰일 수도 있다
let x = 1, y = 3;
alert( y - x );    // 2, 이항 마이너스 연산자는 뺄셈을 해준다.

부호를 반전해주는 단항 마이너스 연산자와 뺄셈에 쓰이는
이항 마이너스 연산자 ( 뺄셈 연산자 ) 는 부호가 같지만 수행하는 연산이 다르다.
두 연산을 구분하는 기준은 피연산자의 개수이다.

2. 이항 연산자 [+]와 문자열 연결

덧셈 연산자 +는 대개 숫자를 더한 결과를 반환한다.

그러나, 이항 연산자 [ + ] 의 피연산자로 문자열이 전달되면 ,
덧셈이 아닌 문자열 병합 ( 연결 ) 이 일어난다.

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

피연산자 중 하나가 문자열이면 다른 하나도 문자열로 변환된다.

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

첫 번째 피연산자가 문자열인지, 두 번째 피연산자가 문자열인지는 중요하지 않으며,
피연산자 중 어느 하나가 문자열이면 다른 하나도 문자열로 변환된다.


연산은 왼쪽에서 오른쪽으로 진행된다.
두 개의 숫자 뒤에 문자열이 오는 경우 , 숫자가 먼저 더해지고 ,
그 후 더해진 숫자와 문자열과의 병합이 이뤄진다.

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

이처럼 이항 덧셈 연산자 +는 문자열 연결과 변환이라는 특별한 기능을 제공한다.
다른 산술 연산자가 오직 숫자형의 피연산자만 다루고 ,
피연산자가 숫자형이 아닌 경우에 그 형을 숫자형으로 바꾸는 것과는 대조적이다.


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

뺄셈 [ - ] 과 나눗셈 [ / ] 연산자는 문자형 피연산자와 관계 없이 수식이 계산 된다.

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"

값을 더해주려면 , 단항 덧셈 연산자를 사용해 피연산자를 숫자형으로 변화시켜야 한다.

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

연산자 우선순위에 의해 단항 덧셈 연산자가 먼저 적용된 후
이할 덧셈 연산자가 적용되어 수식이 계산된다.

4. 연산자 우선순위

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

자바스크립트에서 정의한 연산자 우선순위에 어긋나고 싶다면, 괄호를 사용하면 된다.
괄호는 모든 연산자보다 우선순위가 높기 때문에 연산자 우선순위를 무력화시킨다.

  • 괄호는 모든 연산자보다 우선순위가 높다.
  • 우선순위 숫자가 클수록 먼저 실행된다.
  • 순위가 같으면 왼쪽부터 시작해서 오른쪽으로 연산이 수행된다.

우선순위 테이블(precedence table) 의 일부를 발췌한 표

동일한 기호의 단항 연산자는 이항 연산자보다 우선순위가 더 높다.

5. 할당 연산자

무언가를 할당할 때 쓰이는 할당 연산자 [ = ] 의 우선순위는 3으로 아주 낮다.

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

x = 2 * 2 + 1 과 같은 표현식에서 계산이 먼저 이뤄지고 ,
그 결과가 x에 할당되는 이유가 바로 이 때문이다.


할당 연산자는 여러 개를 연결할 수도 있다. [ 체이닝 ]

let a, b, c;
a = b = c = 2 + 2;
alert( a ); // 4
alert( b ); // 4
alert( c ); // 4

할당 연산자를 여러 개 연결한 경우 , 평가는 우측부터 진행된다.
먼저 가장 우측의 2 + 2가 평가되고 , 그 결과가 좌측의 c, b, a에 순차적으로 할당된다.
모든 변수가 단일 값을 공유하게 된다.


연산자는 항상 값을 반환하며,
덧셈 [ + ] 또는 곱셈 [ * ] 연산자에선 이런 특징이 명확하게 드러난다.
할당 연산자도 이 규칙을 따르며, 할당 연산자 [ = ] 는 값을 반환한다.

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 ) 은 a에 값을 할당하고 ,
그 값인 3 을 반환한다. 반환 값은 이어지는 표현식에 사용된다.

6. 나머지 연산자 [ % ]

나머지 연산자는 [ % ] 기호로 나타내지만 , 비율을 나타내는 퍼센트와는 관련이 없다.

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

alert( 5 % 2 ); // 5를 2로 나눈 후 나머지 1 출력
alert( 8 % 3 ); // 8을 3으로 나눈 후 나머지 2 출력
alert( 6 % 3 ); // 6을 3으로 나눈 후 나머지 0 출력

7. 거듭제곱 연산자 [ ** ]

거듭제곱 연산자 ** 는 표준으로 채택된 지 얼마 안 된 연산자 이다.

자연수 b가 있을 때 , 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)

거듭제곱 연산자는 정수가 아닌 숫자에 대해서도 동작한다.

8. 증가/감소 연산자

숫자를 하나 늘리거나 줄이는 것은 자주 사용되는 연산이다.

  • 증가 ( increment ) 연산자 [ ++ ] 는 변수를 1 증가시킨다.
let counter = 2;
counter++; // counter = counter + 1과 동일하게 동작하지만, 더 짧다.
alert( counter ); // 3
  • 감소 ( decrement ) 연산자 [ -- ] 는 변수를 1 감소시킨다.
let counter = 2;
counter--; // counter = counter - 1과 동일하게 동작하지만, 더 짧다.
alert( counter ); // 1

증가/감소 연산자는 변수에만 쓸 수 있다!

5++와 같이 값에 사용하려고 하면 에러가 발생한다.

[ ++ ] 와 [ -- ] 연산자는 변수 앞이나 뒤에 올 수 있으며 ,

  • counter++와 같이 피연산자 뒤에 올 때는 , "후위형 ( postfix form ) "이라고 부흔다.
  • ++counter와 같이 피연산자 앞에 올 때는 , "전위형 ( prefix form ) "이라고 부른다.

후위형과 전위형은 피연산자인 counter를 1만큼 증가시켜 준다는 점에서 동일한 일을 한다.

두 형의 차이는 [ ++ ] / [ -- ] 의 반환 값을 사용할 때 드러난다.

모든 연산자는 값을 반환한다. 증가 / 감소 연산자도 마찬가지이다.

  • 전위형은 증가/감소 후의 새로운 값을 반환한다.
  • 후위형은 증가/감소 전의 기존 값을 반환한다.
let counter = 1;
let a = ++counter; 
alert(a); // 2

전위형 ++counter 는 counter 를 증가시키고 새로운 값 2를 반환한다.

let counter = 1;
let a = counter++; 
alert(a); // 1

후위형 counter++는 counter 를 증가시키긴 하지만 , 증가 전의 기존 값을 반환한다.


증가, 감소 연산자에 대한 내용 정리

  • 반환 값을 사용하지 않는 경우라면 , 전위형과 후위형엔 차이가 없다.
let counter = 0;
counter++;
++counter;
alert( counter ); // 2
  • 값을 증가시키고 난 후 , 증가한 값을 바로 사용하려면 전위형 증가 연산자를 사용한다.
let counter = 0;
alert( ++counter ); // 1
  • 값을 증가시키지만 , 증가 전의 기존값을 사용하려면 후위형 증가 연산자를 사용한다.
let counter = 0;
alert( counter++ ); // 0

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

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

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

이렇게 코드를 작성하는 게 기술적으로 문제가 있는 것은 아니지만 ,
한 줄에서 여러 가지 일을 동시에 하고 있기 때문에 코드의 가독성이 떨어진다.

코드를 읽을 때 눈을 빠르게 움직이다 보면 counter++ 와 같은 것을 놓치기 쉬워,
변수가 증가했다는 것을 놓칠 수 있다.

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

" 코드 한 줄엔 , 특정 동작 하나 " 에 관련된 내용만 작성하는 게 좋다.

9. 비트연산자

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

비트 연산 시 쓰이는 연산자 목록

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

비트 연산이 어떻게 수행되는지 이해하려면 2진 표현에 대해 알아야 한다.
이 연산자를 쓸 일이 거의 없기에, 연산자가 필요할 때
MDN 의 비트 연산자 문서 문서를 찾아보는것을 추천한다.

10. 복합 할당 연산자

프로그램을 짜다 보면 , 변수에 연산자를 적용하고
그 결과를 같은 변수에 저장해야 하는 경우가 종종 생긴다.

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

이때, [ += ] 와 [ *= ] 연산자를 사용하면 짧은 문법으로 동일한 연산을 수행할 수 있다.

let n = 2;
n += 5;      //  7   ( n = n + 5 )
n *= 2;      // 14   ( n = n * 2 )
alert( n );  // 14

복합 할당 연산자는 산술 연산자와 비트 연산자에도 적용할 수 있다.
[ /= ] , [ -= ] 등의 연산자를 만들 수 있다.

let n = 2;
n *= 3 + 5;
alert( n ); //  16  ( +=의 우측이 먼저 평가되므로 ,  n *= 8 )

복합 할당 연산자의 우선순위는 할당 연산자와 동일하다.
따라서 대다수의 경우, 다른 연산자가 실행된 후에 복합 할당 연산자가 실행된다.

11. 쉼표 연산자

쉼표 ( comma ) 연산자 [ , ] 는 좀처럼 보기 힘들고 , 특이한 연산자 중 하나이다.
코드를 짧게 쓰려는 의도로 가끔 사용된다.

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

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


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

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

쉼표 연산자를 사용한 트릭은 여러 자바스크립트 프레임워크에서 볼 수 있다.
쉼표 연산자는 코드 가독성에 도움이 되지 않아, 정말 필요한 경우에만 사용하는것이 좋다.

12. 과제

전위형과 후위형

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

let a = 1, b = 1;
let c = ++a;         // ?
let d = b++;         // ?

a = 1 , b = 1 ,
++a 전위형 증가 연산자로 a = 2 가 된 후 c 에 할당 c = 2 ,
b++ 후위형 증가 연산자로 b = 1 의 값을 d 에 할당 d = 1 ,
값이 할당 된 후 b값 증가 b = 2 .

a = 2 , b = 2 , c = 2 , d = 1


할당 후 결과 예측하기

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

let a = 2;
let x = 1 + (a *= 2);

a = 2 , ( a *= 2 ) 연산을 하여 a = 4 ,
1 + ( 4 ) 의 값을 x 에 할당하여 x = 5 .

a = 4 , x = 5


형 변환

아래 표현식들의 결과를 예측해 보세요.

"" + 1 + 0
"" - 1 + 0
true + false
6 / "3"
"2" * "3"
4 + 5 + "px"
"$" + 4 + 5
"4" - 2
"4px" - 2
7 / 0
"  -9  " + 5
"  -9  " - 5
null + 1
undefined + 1
" \t \n" - 2

"" + 1 + 0 = " 10 "

피 연산자 중 하나가 문자열인 "" + 1 에서 1은 문자형으로 변환된다 .
공백과 문자열 1을 더한, "" + 1 = " 1 " 이 된다.
그다음 연산 "1" + 0 = " 10 " 이된다.


"" - 1 + 0 = -1

뺄셈 연산자 [ - ] 숫자형만을 인수로 받는다.
빈 문자열 [ "" ] 는 숫자 0으로 변환되어 0 - 1 + 0 = -1 이 된다.


true + false = 1

true = 1 , false = 0 으로 변환되어, 1 + 0 = 1 이 된다.


6 / "3" = 2

나눗셈 연산자 [ / ] 숫자형만을 인수로 받아,
문자열 "3" 은 숫자 3으로 변환되어 6 / 2 = 2 가 된다.


"2" * "3" = 6

곱셈 연산자 [ * ] 숫자형만을 인수로 받아,
문자열 "2" 은 숫자 2로 , 문자열 "3" 은 숫자 3 으로 변환되어 2 * 3 = 6 이 된다.


4 + 5 + "px"

4 + 5 가 계산되어 9 + "px" 피 연산자 중 하나가 문자열이므로 숫자 9가
문자열 "0" 로 변환되어 "9" + "px" = "9px"


"$" + 4 + 5 = "$45"

피 연산자 중 하나가 문자열이므로 숫자 4가 문자열 "4" 로 변환되어,
"$" + "4" = "$4" , 마찬가지로 숫자 5도 문자열 "5" 로 변환되어,
"$4" + "5" = "$45" 가 된다.


"4" - 2 = 2

뺄셈 연산자 [ - ] 숫자형만을 인수로 받아,
문자열 "4" 는 숫자 4 로 변환되어 4 - 2 = 2 가 된다.


"4px" - 2 = NaN

"4px" 는 숫자로 변환할 수 없기 때문에 NaN 이 된다.


7 / 0 = Infinity

실제로 가능하지 않은 계산을 자바스크립트에서 오류로 처리하지 않지만,
0으로 나눗셈한 값을 나타낼 수 없기 때문에 Infinity 이 된다.


" -9 " + 5 = " -9 5 "

피 연산자 중 하나가 문자열이므로 숫자 5가 문자열로 변환되어
" - 9 " + " 5 " = " -9 5 " 가 된다.


" -9 " - 5 = -14

곱셈 연산자 [ * ] 숫자형만을 인수로 받아,
문자열 " -9" 는 숫자 9 로 변환하여, -9 - 5 = - 14 가 된다.


null + 1 = 1

null은 숫자형 0 으로 변환되어, 0 + 1 = 1 이 된다.


undefined + 1 = NaN

undefined는 숫자형으로 변환시 NaN 이 된다.


" \t \n" - 2 = -2

문자열이 숫자형으로 변할 땐 문자열 앞뒤의 공백이 삭제된다.
뺄셈 연산자 앞의 피연산자는 공백을 만드는 문자 \t와 \n, 그 사이의 공백으로 구성된다.
" \t \n"는 숫자형으로 변환 시 길이가 0인 문자열로 취급되어 숫자 0이 된다.
0 -2 = -2 가 된다.


본문 : https://ko.javascript.info/operators

0개의 댓글