자바스크립트 기본 - 기본 연산자와 수학

devheyrin·2022년 4월 12일
0

modern javascript

목록 보기
8/26

‘단항’, ‘이항', ‘피연산자’

  • 피연산자는 연산자가 연산을 수행하는 대상이다. 5 * 2 에는 왼쪽 피연산자 5와 오른쪽 피연산자 2로 총 두 개의 피연산자가 있다. ‘피연산자'는 ‘인수'라는 용어로 불리기도 한다.
  • 피연산자를 하나만 받는 연산자는 단항 연산자라고 한다. 피연산자의 부호를 뒤집는 단항 마이너스 연산자는 단항 연산자의 대표적인 예이다.
    let x = 1;
    
    x = -x;
    alert( x ); // -1,
  • 두 개의 피연산자를 받는 연산자는 이항 연산자라고 한다. 마이너스 연산자는 아래와 같이 이항 연산자로 쓸 수도 있다.
    let x = 1, y = 3;
    alert( y - x );
    부호를 반전해주는 단항 마이너스 연산자와 뺄셈에 쓰이는 이항 마이너스 연산자는 기호는 같지만 수행하는 연산이 다르다. 두 연산을 구분하는 기준은 피연산자의 개수이다.

수학

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

  • +, -, *,
  • % 나머지 연산자
  • ** 거듭제곱 연산자

나머지 연산자

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

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

거듭제곱 연산자

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

거듭제곱 연산자는 정수가 아닌 순자에 대해서도 동작한다. 즉 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'이 출력됩니다.

연산은 왼쪽에서 오른쪽으로 순차 시행되기 때문에 41이 출력된다.

뺄셈과 나눗셈 연산자는 숫자형이 아닌 경우에 그 형을 숫자형으로 바꾼 후 연산을 수행하지만, 덧셈 연산자는 연결과 변환이라는 특별한 기능을 제공한다.

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

덧셈 연산자 + 는 단항 연산자로도 사용할 수 있다. 피연산자가 숫자가 아닌 경우 덧셈 연산자를 붙이면 숫자형으로의 변환이 일어난다.

// 숫자에는 아무런 영향을 미치지 않는다 
let x = 1;
alert( +x ); // 1

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

// 숫자형이 아닌 피연산자는 숫자형으로 변화한다. 
alert( +true ); // 1
alert( +"" );   // 0

개발을 하다보면 문자열을 숫자로 변환해야 하는 경우가 자주 생긴다. 예를 들어 HTML 폼 필드에서 값을 가져오면 그 값은 문자열 형태이므로 + 연산자로 더하면 문자열로 변해서 연결된다.

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

alert( apples + oranges );

숫자로 더하고 싶다면 단항 덧셈 연산자를 사용해 피연산자를 숫자형으로 변환시켜주어야 한다.

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

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

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

그런데 왜 이항 덧셈 연산자가 적용되기 전에 단항 덧셈 연산자가 먼저 적용될까? 그 이유는 연산자 우선순위 때문이다.

연산자 우선순위

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

예를 들어 1 + 2 * 2 라는 식이 있을 때 곱셈이 먼저, 덧셈이 나중에 일어난다.

자바스크립트에는 정해진 연산자 우선순위가 있지만, 괄호를 사용하면 다른 모든 연산자보다 우선하게 만들 수 있다. (1 + 2) * 2 는 덧셈을 먼저, 곱셈을 나중에 수행하는 것과 같다.

우선순위 숫자가 클수록 먼저 실행되고, 순위가 같으면 왼쪽부터 시작해서 오른쪽으로 연산이 수행된다.

대략적인 우선순위는 다음과 같다. 단항 연산자가 이항 연산자보다 우선순위가 높다는 것을 알 수 있다.

  • 단항 덧셈 > 단항 부정 > 지수 > 곱셈 > 나눗셈 > 덧셈 > 뺄셈 > 할당 ..

할당 연산자

= 는 무언가를 할당할 때 쓰이는 할당 연산자이다. 우선순위는 3으로 매우 낮기 때문에 계산이 모두 이루어진 후 할당이 이루어진다.

값을 변환하는 할당 연산자

= 는 연산자이기 때문에 함축성을 내포하고 있다.

x = value 를 호출하면 value 가 x에 저장되고, 이에 다른 연산을 더하여 value 가 반환된다.

이러한 특징을 이용한 표현식을 살펴보자!

let a = 1;
let b = 2;

let c = 3 - (a = b + 1); // a에 값을 할당하고, 그 값인 3을 반환한다. 

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

여러 자바스크립트 라이브러리에서 이런 식으로 할당연산자를 사용하기 때문에 동작 원리는 이해해야 하지만, 직접 코드를 작성할 때는 이런 방식을 사용하지 않는 것이 좋다!

할당 연산자 체이닝

할당 연산자는 여러 개를 연결할 수 있다.

let a, b, c;

a = b = c = 2 + 2;

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

할당 연산자를 여러 개 연결하면 우측부터 진행된다. 가장 우측의 2+2가 실행되고 그 결과가 c, b, a 순서로 할당된다.

그러나 연산자를 체이닝하는것보다는 가독성을 위해 줄을 나눠 작성하는 것이 좋다.

복합 할당 연산자

변수에 연산자를 적용하고 그 결과를 같은 변수에 저장해야 하는 경우 다음과 같이 복합 할당 연산자를 사용한다.

let n = 2;
n += 5; // n은 7이 된다(n = n + 5와 동일).
n *= 2; // n은 14가 된다(n = n * 2와 동일).

alert( n ); // 14

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

증가/감소 연산자

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

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

증가/감소 연산자는 변수 앞이나 뒤에 올 수 있다. 피연산자 뒤에 올 때는 후위형, 피연산자 앞에 올 때는 전위형이라고 부른다.

전위형은 증가/감소 후 새로운 값을 반환하고, 후위형은 증가/감소 전의 기존 값을 반환한다.

  • 전위형
let counter = 1;
let a = ++counter;

alert(a); // 2
  • 후위형
let counter = 1;
let a = counter++; 

alert(a); // 1
  • 반환 값을 사용하지 않는다면 전위형과 후위형에는 차이가 없다.
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++ ); // counter++는 '기존'값을 반환하기 때문에 2가 출력된다. 

위와 같은 코드는 가독성이 떨어지기 때문에, 코드 한 줄에는 특정 동작 하나만 작성하도록 아래와 같이 수정하는 것이 좋다.

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

비트 연산자

비트 연산자는 인수를 32비트 정수로 변환하여 이진 연산을 수행한다. 2진 표현에서 숫자를 다뤄야 할 때 쓰이므로 흔하게 쓰이지는 않는다. 그러나 암호를 다뤄야 할 때는 비트 연산자가 유용하기 때문에 필요하다면 MDN의 비트 연산자 문서를 보는 것이 좋다.

쉼표 연산자

코드를 짧게 쓰려는 의도로 가끔 사용된다. 여러 표현식을 코드 한 줄에서 평가할 수 있게 해 준다. 표현식 각각이 모두 평가되지만, 마지막 표현식의 평가 결과만 반환된다.

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

alert( a ); // 7 (3 + 4의 결과)

여러 동작을 하나의 줄에서 처리하려는 복잡한 구조에서 주로 사용한다.

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

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

헷갈리는 연산 결과

null + 1 = 1 // 숫자형으로 변환 시 null은 0
undefined + 1 = NaN // undefined는 숫자형으로 변환시 NaN
" \t \n" - 2 = -2 // 문자열이 숫자형으로 변할 땐 문자열 앞뒤의 공백이 삭제된다. 
									// 뺄셈 연산자 앞의 피연산자는 공백을 만드는 문자 \t와 \n, 그 사이의 “일반적인” 공백으로 구성 
									// 따라서 " \t \n"는 숫자형으로 변환 시 길이가 0인 문자열로 취급되어 숫자 0이 된다. 
profile
개발자 헤이린 🔜 프로덕트 매니저로 나아가는 중!

0개의 댓글