[Javascript] 연산자 (Operator)

유동균·2022년 12월 4일
0

JavaScript

목록 보기
3/13
post-thumbnail

1. 표현식(Expression)

  • 값은 다양한 방법으로 생성할 수 있다.

  • 여기서 말하는 다양한 방법이란 표현식을 말한다. 프로그래밍 언어에서 표현식은 중요한 역할을 한다.

  • 표현식은 리터럴, 식별자, 연산자, 함수 호출 등의 조합.

    Literal 리터럴 : 소스코드 안에서 직접 만들어 낸 상수 값 자체, 값을 구성하는 최소 단위
    Identifier 식별자 : 자바스크립트에서 이름을 붙일 때 사용하는 단어

  • 표현식은 평가(Evaluation.표현식을 실행하여 하나의 값을 만드는 과정)되어 하나의 값을 만든다. 즉, 표현식은 하나의 값으로 평가될 수 있는 문이다

  • 표현식은 평가되어 값을 만들지만 그 이상의 행위를 할 수 없다.

  • 표현식의 역할은 값을 생성하는 것이다.

2. 문(Statement)

  • 문은 자바스크립트 엔진에게 내리는 명령어.
  • 문이 실행되면 무슨일인가가 일어나게 된다.
  • 변수 선언문을 실행하면 변수가 선언이 되고, 할당문을 실행하면 할당이 된다. 또 조건문을 실행하면 주어진 조건에 따라 코드 블록( {...} )의 실행이 결정되고, 반복문을 실행하면 코드 블록이 반복 실행된다.
  • 문은 리터럴, 연산자, 표현식, 키워드 등으로 구성되며 세미콜론(;)으로 끝나야 한다.
    (코드블록은 제외)
  • 자바스크립트의 모든 코드는 문 또는 표현식이다. 표현식과 문은 유사하기 때문에 구별이 어려울수 있다.
  • 문은 let, const, function, class와 같은 선언 키워를 사용하여 변수나 함수를 생성하기도 하고 if, while, for 문과 같은 제어문을 생성하여 프로그램의 흐름을 제어하기도 한다.
  • 문의 역할은 표현식으로 생성한 값을 사용해 컴퓨터에게 명령을 내리는 것.
/// 예제
let a = 2 * 10;	// 표현식 a = 2 * 10을 포함하는 선언문
a = 999;		// 표현식이지만 할당문이기도 하다.
  • 예제의 1행인 선언문은 표현식이 아닌 문이기 때문에 값으로 평가될 수 없다. 따라서 선언문은 아래와 같이 값처럼 사용할 수 없다.
let sta  = let a = 2 * 10;
  • 이에 반해 예제의 2행인 할당문은 할당문이기도 하면서 표현식이기 때문에 아래와 같이 값처럼 사용할 수 있다.
let sta = a = 999;

3. 연산자 (Operator)

  • 연산자는 하나 이상의 표현식을 대상으로 산술, 할당, 비교, 논리, 타입 연산 등을 수행해 하나의 값을 만든다. 이때 연산의 대상을 피연산자(Operand)라 한다.
  • 피연산자도 평가되어 하나의 값이 되므로 표현식이고 피연산자를 연산자와 결합한 연산자 표현식도 표현식이다.

3.1. 산술 연산자(Arithmetic Operator)

  • 산술 연산자는 피연산자를 대상으로 수학적 계산을 수행해 새로운 숫자 값을 만든다.
  • 산술 연산을 할 수 없는 경우에는 NaN을 반환한다.

3.1.1. 이항 산술 연산자

  • 이항 산술 연산자는 2개의 피연산자를 대상으로 연산하여 숫자 타입의 값을 만든다.
  • 모든 이항 산술 연산자는 피연산자의 값을 변경하는 부수 효과(Side effect)가 없다.
    다시말해, 어떤 산술 연산을 해도 피연산자의 값이 바뀌는 경우는 없고 단지 새로운 값을 만들 뿐이다.
이항 산술 연산자의미
+덧셋
-뺄셈
*곱셈
/나눗셈
%나머지
**제곱
5 + 2	// 7
5 - 2  	// 3
5 * 2  	// 10
5 / 2  	// 2.5
5 % 2  	// 1
5 ** 2  // 25 5의 2제곱

3.1.2. 단항 산술 연산자

  • 단항 산술 연산자는 1개의 피연산자르 대상으로 연산한다.
  • 증가/감소(++/--) 연산자(Prefix increment/decrement operator)는
    피연산자의 값을 변경하는 부수 효과가 있다.
    다시말해, 증가/감소 연산을 하면 피연산자의 값이 바뀐다.
단항 산술 연산자의미
++증가
--감소
+효과가 없음
-양수를 음수로, 음수를 양수로 반전한 값을 반환
  • 증가/감소 연산자는 위치에 의미가 있다.
    • 피연산자의 앞에 위치한 전위 증가/감소 연산자는 먼저 피연산자의 값을 증가/감소시킨 후, 다른 연산을 수행한다.
    • 피연산자의 뒤에 위치한 후위 증가/감소 연산자는 피연산자의 값을 증가/감소 시키기 전, 다른 연산을 먼저 수행한다.
let a = 5;
let result;

// 선대입 후증가
result = a++;
console.log(result, a);	// 5, 6

// 선증가 후대입
result = ++a;
console.log(result, a);	// 7, 7

// 선대입 후감소
result = a--;
console.log(result, a);	// 7, 6

// 선감소 후대입
result = --a;
console.log(result, a);	// 5, 5

3.1.3. 문자열 연결 연산자

  • + 연산자는 피연산자 중 하나 이상이 문자열인 경우 문자열 연결 연산자로 동작한다. 그 외의 경우에는 덧셈 연산자로 동작한다.
// 문자열 연결 연산자
'Hello' + 'World'	// 'HelloWorld'
'1' + '2'			// '12'
'1' + 100			// '1100' (문자열'1'과 숫자열100을 더할경우 문자열 '1100')

// 산술 연산자
1 + true			// 2 (true가 타입이 자동으로 숫자로 변경됨, true→1)
false + true		// 1 (false→0, true→1)
1 + null			// 1 (null→0)
1 + undefined		// NaN (undefined→NaN)
  • 이처럼 타입이 강제변환 되는 것을 암묵적 타입변환(Implicit coercion) 또는 타입 강제 변환(Type coercion)이라고 한다.

3.2. 할당 연산자

  • 할당 연산자는(Assignment Operator) 오른쪽에 있는 피연산자의 평가 결과를 왼쪽에 있는 변수에 할당한다.
  • 할당 연산자는 왼쪽의 변수에 값을 할당 하므로 부수 효과가 있다.
할당 연산자사례동일표현
=x = yx = y
+=x += yx = x + y
-=x -= yx = x - y
*=x *= yx = x * y
/=x /= yx = x / y
%=x %= yx = x % y
**=x **= yx = x ** y
let a;

a = 4;		// 4
a += 2;		// 6
a -= 2;		// 4
a *= 2;		// 8
a /= 2;		// 4
a **= 2;	// 16
a /+ 2;		// 8
  • 할당 연산은 하나의 값으로 평가되는 표현식이다. 할당 표현식은 할당된 값으로 평가된다.
    따라서 아래의 예제에서 a에 할당된 숫자 값 100으로 평가된다.
let a;
console.log(a = 100);	// 100
  • 따라서 아래와 같이 할당 연산 표현식을 다른 변수에 할당 할 수 있다.
let a, b;
b = a = 100;	// 연쇄 할당(Chained assignment)
console.log(x, y);	// 100, 100

3.3. 비교 연산자(Comparison Operator)

  • 비교연산자는 양쪽의 피연산자들을 비교하여 불리언 값을 반환한다.

3.3.1. 동등 / 일치 비교 연산자

비교 연산자의미사례설명
==동등 비교x == yx와 y의 값이 같음
===일치 비교x === yx와 y의 값과 타입이 같음
!=부등 비교x != yx와 y의 값이 다름
!==불일치 비교x !== yx와 y의 값과 타입이 다름
  • 동등 비교 연산자는 양쪽의 피연산자들을 비교할 때 암묵적 타입 변환을 일치시킨 후 같은 값을 갖는지 비교한다. 따라서 양쪽 피연산자들의 타입이 다르더라도 값이 같으면 true를 반환한다.
5 == 5		// true
5 == '5'	// true
  • 동등 비교 연산자는 편리한 경우도 있지만 수많은 부작용을 일으키므로 사용하지 않는 편이 좋다.
'' == '0'		// false
0 == ''			// true
0 == '0'			// true
false == 'false'	// false
false == '0'		// true
false == undefined	// false
false == null		// false
null == undefined	// true
  • 위처럼 동등 비교 연산자는 예측하기 어려운 결과를 만들어낸다.
    하지만 일치 비교 연산자는 양쪽의 피연산자들의 타입과 값이 같은 경우에 한하여 true를 반환한다.
5 === 5	// true
5 === '5'	// false
null === undefined	// false
  • 일치 비교 연산자의 NaN 비교 주의
NaN === NaN;	// false (NaN은 자신과 일치하지 않는 유일한 값)
  • 일치 비교 연산자의 숫자 0 비교 주의
0 === -0	// true

3.3.2. 대소 관계 비교 연산자

  • 대소 관계 비교 연산자는 피연산자의 크기를 비교하여 불리언 값을 반환한다.
대소 관계 비교 연산자예제설명
>x > yx가 y보다 크다
<x < yx가 y보다 작다
>=x >= yx가 y보다 크거나 같다
>=x >= yx가 y보다 작거나 같다
  • 비교하려는 피연산자의 값의 타입이 다르면 숫자열로 반환하여 비교한다
'2' > 1		// true(2 > 1)
1 == '01'	// true(1 == 1)

3.4. 삼항 조건 연산자 (Ternary operator)

  • 조건의 평가 결과에 따라 반환할 값을 결정하고 부수 효과는 없다.
// 삼항 조건 연산자의 표현식
조건식 ? 조건식이 true일때 반환할 값 : 조건식이 false일때 반환할 값
  • 물음표 ? 앞의 첫번째 피연산자가 조건식, 불리언 타입의 값으로 평가될 표현식.
    만약 조건식의 평가 결과가 불리언 값이 아니면 불리언 값으로 암묵적 타입 변환.
  • 조건식이 true이면 콜론 : 앞의 값이, false이면 콜론 : 뒤의 값이 반환된다.
let a = 2;
// a가 짝수이면 '짝수', 홀수이면 '홀수'를 반환한다.
// a % 2 = 0 이므로 0은 false로 암묵적 타입 변환
let result = a % 2 ? '짝수' : '홀수';
console.log(result);	// '짝수'

3.5. 논리 연산자(Logical Operator)

  • 논리 연산자는 양쪽의 피연산자들(부정 논리 연산자의 경우, 오른쪽의 피연산자)를 논리 연산한다.
  • 논리 부정 ! 연산자는 언제나 불리언 값을 반환한다. 하지만 논리합 || 연산자와 논리곱&& 연산자는 일반적으로 불리언 값을 반환하지만 반디시 불리언 값을 반환해야 하는것은 아니다.
논리 연산자의미
||논리합(OR)
&&논리곱(AND)
!부정(NOT)
// 논리합(||, OR) 연산자 - 하나라도 true인 경우 true
true || true   // true
true || false  // true
false || true  // true
false || false // false

// 논리곱(&&, AND) 연산자 - 모두 true이여야 true
true && true   // true
true && false  // false
false && true  // false
false && false // false

// 논리 부정(!, NOT) 연산자
!true	// false
!false	// true
!0		// true (피연산자가 불리언 값이 아닌 경우 암묵적 타입 변환)

3.5.1. 논리합 연산자

  • 논리합 연산자는 if문에서 자주 사용된다. 주어진 조건 중 하나라도 true인지 확인하기 위해서
let hour = 12;
let isWeekend = true;

if (hour < 10 || hour > 18 || isWeekend) {
	console.log('Close');	// 'Close'
} else {
	console.log('Open');	// 실행되지 않음
}
  • 논리합 연산자의 알고리즘
let result = value1 || value2 || value3;
  • 가장 왼쪽의 피연산자부터 시작해서 오른쪽으로 나아가며 피연산자를 평가.
  • 각각의 피연산자를 불리언 값으로 변환 후 그 값이 true이면 연산을 멈추고
    해당 피연산자의 변환 전 원래 값을 반환.
  • 피연산자를 모두 평가한 경우(모든 피연산자가 false로 평가되는 경우)에는 마지막 피연산자를 반환.
let a = undefined || null || 0;
console.log(a);			// 0 (모두 false이므로 마지막 값을 반환)

// 단락 평가
true || alert('true');	// 왼쪽 조건이 true이므로 alert이 실행되지 않음
false || alert('false');

3.5.2. 논리곱 연산자

  • 논리곱 연산자의 알고리즘
let result = value1 && value2 && value3;
  • 가장 왼쪽의 피연산자부터 시작해서 오른쪽으로 나아가며 피연산자를 평가.
  • 각각의 피연산자를 불리언 값으로 변환 후 그 값이 false이면 연산을 멈추고
    해당 피연산자의 변환 전 원래 값을 반환.
  • 피연산자를 모두 평가한 경우(모든 피연산자가 true로 평가되는 경우)에는 마지막 피연산자를 반환.

3.6. 쉼표 연산자

  • , 쉼표 연산자는 왼쪽 피연산자부터 차례대로 피연산자를 평가하고 마지막 피연산자의 평가가 끝나면 마지막 피연산자의 평가 결과를 반환한다.
let a = (1 + 2, 3 + 4);
console.log(a);	// 7

3.7. 그룹 연산자

  • () 그룹 연산자는 그룹 내의 표현식을 최우선으로 평가한다.
    그룹 연산자를 사용하면 연산자의 우선 순위를 1순위로 높일 수 있다.
10 * 2 + 3		// 23
10 * (2 + 3)	// 50

3.8. typeof 연산자

  • typeof 연산자는 자신의 뒤에 위치한 피연산자의 데이터 타입을 문자열로 반환한다.
typeof ''              // "string"
typeof 1               // "number"
typeof NaN             // "number"
typeof true            // "boolean"
typeof undefined       // "undefined"
typeof Symbol()        // "symbol"
typeof null            // "object"
typeof []              // "object"
typeof {}              // "object"
typeof new Date()      // "object"
typeof /test/gi        // "object"
typeof function () {}  // "function"
  • null의 경우 object를 반환 하는데 이는 자바스크립트 첫번째 버전에서 설계된 것을 현재 버전에 반영하지 못하고 있기 때문이다. (참고 : The history of “typeof null”)

3.9. nullish 병합 연산자

nullish 병합 연산자(nullish coalescing operator) ?? 를 사용하면 짧은 문법으로 여러 피연산자 중 그 값이 확정되어있는 변수를 찾을 수 있다.

  • a ?? b 의 평과 결과는 다음과 같다.
    • anull도 아니고 undefined도 아니면 a
    • 그 외의 경우 b
let fisrtName = null;
let lastName = null;
let nickName = 'Sonny'
console.log(fisrtName ?? lastName ?? nickName ?? "익명");	// Sonny

3.9.1 ??|| 의 차이점

위의 예제에서 ??||로 바꿔도 결과는 동일하다.
하지만 차이점이 있는데,

  • || 는 첫번째 truthy 값을 반환
  • ?? 는 첫번째 '정의된 값(defined)'을 반환

null, undefined, 숫자 0 을 구분 지어야할 때 중요한 역할을 한다.

let height = 0;

console.log(height ?? 100);	// 0
console.log(height || 100);	// 100

3.9.2 ?? 사용시 주의사항

??는 연산자 우선 순위가 낮기 때문에 사용 시 괄호를 추가하는게 좋다

let height = null;
let width = null;

let box = (height ?? 100) * (width ?? 50);
console.log(box)	// 5000

괄호를 사용하지 않을 경우

let box = height ?? (100 * width) ?? 50;

위의 예제처럼 작동한다.

또한 ??는 안정성 이유 때문에 ||, &&와 함께 사용하지 못한다.
제약을 피하기 위해선 괄호를 사용한다.

참고 문헌

PoiemaWeb: 웹 프로그래밍 튜토리얼 https://poiemaweb.com
모던 JavaScript 튜토리얼 https://ko.javascript.info
벨로퍼트와 함께하는 모던 자바스크립트 https://learnjs.vlpt.us
MDN https://developer.mozilla.org/ko/

0개의 댓글