항해 99 1주차 1-7

youngsung·2023년 2월 16일
0

javascript

목록 보기
10/12

기본연산자와 수학

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

연산자에 대해 학습하기 전에, 앞으로 자주 등장하게 될 용어 몇 가지를 정리해 보겠습니다.

  • 피연산자(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, 이항 마이너스 연산자는 뺄셈을 해줍니다.

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

수학

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

나머지 연산자 %

나머지 연산자(remainder operator)는 % 기호로 나타내지만, 비율을 나타내는 퍼센트와 관련이 없습니다.

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

거듭제곱 연산자 **

거듭제곱 연산자(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)

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

alert( 4 ** (1/2) ); // 2 (1/2 거듭제곱은 제곱근)
alert( 8 ** (1/3) ); // 2 (1/3 거듭제곱은 세제곱근)

이항 연산자 '+'와 문자열 연결

이항 연산자 +의 피연산자로 문자열이 전달되면 덧셈 연산자는 덧셈이 아닌 문자열을 병합(연결)합니다.

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

따라서 이항 연산자 +를 사용할 때는 피연산자 중 하나가 문자열이면 다른 하나도 문자열로 변환된다는 점에 주의해야 합니다.

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

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

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(...)와 동일한 일을 할 수 있게 해줍니다.
개발을 하다 보면 문자열을 숫자로 변환해야 하는 경우가 자주 생깁니다. HTML 폼(form) 필드에서 값을 가져왔는데 그 값이 문자형일 때 같이 말이죠. 실제로 폼에서 가지고 온 값은 대개 문자열 형태입니다.

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

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

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

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

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

// `Number(...)`를 사용해서 같은 동작을 하는 코드를 작성할 수 있지만, 더 기네요.
// alert( Number(apples) + Number(oranges) ); // 5

위 식은 우리가 의도한 대로 단항 덧셈 연산자가 먼저 문자열을 숫자로 변환시키고, 이항 덧셈 연산자가 그 결과들을 더해주고 있습니다.

연산자 우선순위

순위 연산자 이름 기호
… … …
17 단항 덧셈 +
17 단항 부정 -
16 지수 *
15 곱셈

15 나눗셈 /
13 덧셈 +
13 뺄셈 -
… … …
3 할당 =
… … …

할당 연산자

무언가를 할당할 때 쓰이는 =도 연산자입니다. 이 연산자는 할당(assignment) 연산자라고 불리는데, 우선순위는 3으로 아주 낮습니다.
x = 2 * 2 + 1과 같은 표현식에서 계산이 먼저 이뤄지고, 그 결과가 x에 할당되는 이유가 바로 이 때문입니다.

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

괴상한 코드라고 느껴지겠지만, 여러 자바스크립트 라이브러리에서 이런 식으로 할당 연산자를 사용하고 있기 때문에 동작 원리를 이해할 수 있어야 합니다.

다만, 직접 코드를 작성할 땐 이런 방식을 사용하지 않기를 바랍니다. 이런 트릭을 사용하면 코드가 명확하지 않을 뿐만 아니라 가독성도 떨어지기 때문입니다.

할당 연산자 체이닝

let a, b, c;

a = b = c = 2 + 2;

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

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

그런데 되도록이면 연산자를 체이닝 하는것 보다 가독성을 위해 아래와 같이 줄을 나눠 코드를 작성하길 권유드립니다.

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

복합 할당 연산자

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

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

이런 ‘복합 할당’ 연산자는 산술 연산자와 비트 연산자에도 적용할 수 있습니다. /=, -= 등의 연산자를 만들 수 있죠.

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

let n = 2;

n *= 3 + 5;

alert( n ); // 16  (*=의 우측이 먼저 평가되므로, 위 식은 n *= 8과 동일합니다.)

증가·감소 연산자

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

자바스크립트에서는 이런 연산을 해주는 연산자를 제공합니다.

  • 증가(increment) 연산자 ++는 변수를 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를 반환합니다. 따라서 alert는 2를 표시합니다.

let counter = 1;
let a = counter++; // (*) ++counter를 counter++로 바꿈

alert(a); // 1

(*)로 표시한 줄의 후위형 counter++는 counter를 증가시키긴 하지만, 증가 전의 기존 값을 반환합니다. 따라서 alert는 1을 표시합니다.

증가, 감소 연산자에 대한 내용을 정리하면 아래와 같습니다.

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

비트 연산자

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

이런 비트 조작 관련 연산자는 자바스크립트뿐만 아니라 대부분의 프로그래밍 언어에서 지원합니다.

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

비트 연산자는 저수준(2진 표현)에서 숫자를 다뤄야 할 때 쓰이므로 흔하게 쓰이진 않습니다. 웹 개발 시엔 이런 일이 자주 일어나지 않기 때문에 비트 연산자를 만날 일은 거의 없죠. 그렇긴 해도 암호를 다뤄야 할 땐 비트 연산자가 유용하기 때문에 때가 되면 MDN의 비트 연산자 문서를 보시는 걸 추천합니다.

profile
To Infinity and Beyond

0개의 댓글