해당 글의 내용은 poiemaweb 을 읽고 요약하여 재정리한 내용입니다.
이번에는 JavaScript lesson 7~9에 해당되는 연산자, 제어문, 타입 변환에 대해 알아보겠습니다.
연산자(Operator)
표현식과 연산자
표현식(expression)은 리터럴, 식별자, 연산자, 함수 호출 등의 조합을 말합니다.
// 리터럴 표현식
10
// 식별자 표현식
sum
// 연산자 표현식
10 + 20
// 함수/메소드 호출 표현식
square()
결국 하나의 값이 되므로 표현식과 값은 동등한 관계, 즉 동치(Equivalent)가 됩니다.
연산자 표현식은 표현식을 결합해 새로운 값을 만들어 내는 가장 일반적인 표현식 입니다.
이처럼 표현식은 다른 표현식의 일부가 되어 새로운 값을 만들어낼 수 있습니다.
문과 표현식, 연산자란?
해당 파트에 대해서는 내용이 반복되기에 이전 글이나 원본 글을 참고하시기 바랍니다 😊
산술 연산자
피연산자를 대상으로 수학적 계산을 수행하며 새로운 숫자 값을 만드는 연산자 입니다.
산술 연산을 할 수 없는 경우에는 NaN
을 반환합니다.
이항 산술 연산자
2개의 피연산자를 대상으로 피연산자의 값이 바뀌는 것이 아닌 새로운 값을 만들어 줍니다.
+
: 덧셈, -
: 뺄셈, *
: 곱셈, /
: 나눗셈, %
: 나머지
단항 산술 연산자
1개의 피연산자를 대상으로 연산하며, 증가/감소 연산자는 피연산자의 값을 변경하는 효과가 있습니다.
++
: 증가, --
: 감소, -
: 양수 → 음수 / 음수 → 양수로 값 전환
이러한 증가/감소 연산자는 위치에 의미가 있습니다.
피연산자 앞에 위치한 전위 증가/감소 연산자(Prefix increment/decrement operator)는 먼저 피연산자의 값을 증가/감소시킨 후, 다른 연산을 수행 합니다.
피연산자 뒤에 위치한 후위 증가/감소 연산자(Postfix increment/decrement operator)는 먼저 다른 연산을 수행한 후, 피연산자의 값을 증가/감소 시킵니다.
헷갈리시는 분들은 아래의 코드를 직접 콘솔에 쳐보면 도움이 됩니다.
var x = 5, result;
// 선대입 후증가 (Postfix increment operator)
result = x++;
console.log(result, x); // 5 6
// 선증가 후대입 (Prefix increment operator)
result = ++x;
console.log(result, x); // 7 7
// 선대입 후감소 (Postfix decrement operator)
result = x--;
console.log(result, x); // 7 6
// 선감소 후대입 (Prefix decrement operator)
result = --x;
console.log(result, x); // 5 5
문자열 연결 연산자
+
연산자는 피연산자 중 하나 이상이 문자열인 경우 문자열 연결 연산자로 동작합니다.
'1' + 2 = '12'
⇒ 이 경우에도 문자열로 연결되었다는 것을 알 수 있습니다.
이에 대해 타입 변환이 일어나는 것은 이후에 살펴보도록 하겠습니다.
할당 연산자
우항에 있는 피연산자의 평가 결과를 좌항에 있는 변수에 할당합니다.
좌항의 변수에 값을 할당하므로 부수 효과가 있다고 할 수 있습니다.
할당 연산자 | 사례 | 동일 표현 |
---|---|---|
= | x = y | x = y |
+= | x += y | x = x + y |
-= | x -= y | x = x - y |
*= | x *= y | x = x * y |
/= | x /= y | x = x / y |
%= | x %= y | x = x % y |
비교 연산자
좌항과 우항의 피연산자를 비교하여 boolean값을 반환합니다.
if
문이나 for
문과 같은 제어문의 조건식에서 주로 사용합니다.
동등 / 일치 비교 연산자
비교 연산자 | 의미 | 사례 | 설명 |
---|---|---|---|
== | 동등 비교 | x == y | x와 y의 값이 같음 |
=== | 일치 비교 | x === y | x와 y의 값과 타입이 같음 |
!= | 부등 비교 | x != y | x와 y의 값이 다름 |
!== | 불일치 비교 | x !== y | x와 y의 값과 타입이 다름 |
동등 비교(==) 연산자는 좌항과 우항의 피연산자를 비교할 때 암묵적 타입 변환을 통해 타입을 일치시킨 후 같은 값을 갖는지 비교합니다.
따라서 좌항과 우항의 피연산자가 타입은 다르더라도 암묵적 타입 변환 후에 같은 값을 수 있으면 true
를 반환합니다.
일치 비교(===) 연산자는 좌항과 우항의 피연산자가 타입도 같고 값도 같은 경우에 한하여 true
를 반환합니다.
일치 비교 연산자에서 NaN
은 자신과 일치하지 않는 유일한 값이어서 숫자가 NaN
인지 알아 보려면 빌트인 함수 isNaN
을 사용합니다.
대소 관계 비교 연산자
대소 관계 비교 연산자 | 예제 | 설명 |
---|---|---|
> | x > y | x가 y보다 크다 ✕ |
< | x < y | x가 y보다 작다 ✕ |
>= | x >= y | x가 y보다 같거나 크다 ✕ |
<= | x <= y | x가 y보다 같거나 크다 ✕ |
피연산자의 크기를 비교하여 boolean 값을 반환합니다.
삼항 조건 연산자
조건식의 평가 결과에 따라 반환할 값을 결정하며, 표현식은 다음과 같습니다.
조건식 ? 조건식이 ture일때 반환할 값 : 조건식이 false일때 반환할 값
물음표 앞이 조건식이며 참이면 콜론(:) 앞의 피연산자가 평가되어 반환되고, 거짓이면 콜론(:) 뒤의 피연산자가 평가되어 반환 됩니다.
논리 연산자
우항과 좌항의 피연산자(부정 논리 연산자의 경우, 우항의 피연산자)를 논리 연산 합니다.
!
연산자는 boolean 값을 언제나 반환(암묵적 타입 변환됨을 의미)하지만 논리합, 논리곱 연산자는 일반적으로 boolean 값을 반환하지만 반드시 그 값을 반환해야 하는 것은 아닙니다.
의미와 예시는 다음과 같습니다.
논리 연산자 | 의미 |
---|---|
|| | 논리합(OR) |
&& | 논리곱(AND) |
! | 부정(NOT) |
// 논리합(||) 연산자
true || true // true
true || false // true
false || true // true
false || false // false
// 논리곱(&&) 연산자
true && true // true
true && false // false
false && true // false
false && false // false
// 논리 부정(!) 연산자
!true // false
!false // true
쉼표 연산자
왼쪽 피연산자부터 차례대로 피연산자를 평가하고 마지막 피연산자의 평가가 끝나면 마지막 피연산자의 평가 결과를 반환 합니다.
var x, y, z;
x = 1, y = 2, z = 3; // 3
그룹 연산자
그룹 내의 표현식을 최우선으로 평가하게 되어 연산자의 우선순위를 1순위로 높일 수 있습니다.
10 * 2 + 3 // 23
10 * (2 + 3) // 50
typeof 연산자
자신의 뒤에 위치한 피연산자의 데이터 타입을 문자열로 반환 합니다.
typeof 연산자는 7가지 문자열 string
, number
, boolean
, undefined
, symbol
, object
, function
중 하나를 반환 합니다.
null
값은 null
이 아닌 object
로 반환하기에 해당 연산자가 아닌 일치 연산자(===)를 사용하도록 합니다.
8. 제어문(Control Flow)
주어진 조건에 따라 코드 블록을 실행(조건문)하거나 반복 실행(반복문)할 때 사용합니다.
블록문
0개 이상의 문들을 중괄호로 묶은 것으로 코드 블록 또는 블록이라고 부릅니다.
문의 끝에는 세미 콜론(;)을 붙이는 것이 일반적이지만 블록문은 세미콜론을 붙이지 않습니다.
조건문
주어진 조건식(conditional expression)의 평가 결과에 따라 코드 블럭(블록문)의 실행을 결정 합니다.
조건식은 불리언 값으로 평가될 수 있는 표현식이며 2가지의 조건문이 있습니다.
if..else 문
if (조건식) {
// 조건식이 참이면 이 코드 블록이 실행된다.
} else {
// 조건식이 거짓이면 이 코드 블록이 실행된다.
}
논리적 참, 거짓에 따라 실행할 코드 블록을 결정하며, boolean 값으로 강제 변환되어 구별합니다.
조건식을 추가하고 싶을 때는 else if
문을 사용하고 여러 번 사용할 수 있습니다.
또, 해당 문은 삼항 조건 연산자로 바꿔쓸 수 있습니다.
switch 문
switch (표현식) {
case 표현식1:
switch 문의 표현식과 표현식1이 일치하면 실행될 문;
break;
case 표현식2:
switch 문의 표현식과 표현식2가 일치하면 실행될 문;
break;
default:
switch 문의 표현식과 일치하는 표현식을 갖는 case 문이 없을 때 실행될 문;
}
switch 문의 표현식을 평가하여 그 값과 일치하는 표현식을 갖는 case
문으로 실행 순서를 이동시킵니다.
switch 문의 표현식과 일치하는 표현식을 갖는 case
문이 없다면 실행 순서는 default
문으로 이동합니다.
default
옵션으로 사용할 수도 있고 사용하지 않을 수도 있습니다.
switch 문의 표현식은 boolean 값보다는 문자열, 숫자 값인 경우가 많아서 논리적 참, 거짓보다는 다양한 case
에 따라 실행할 코드 블록을 결정할 때 사용합니다.
break
키워드로 구성된 break
문은 코드 블록에서 탈출하는 역할을 수행합니다.
break
문이 없다면 case
문의 표현식과 일치하지 않더라도 실행 순서는 다음 case
문으로 연이어 이동하며, default 문의 실행이 종료되면 switch 문을 빠져나갑니다.
반복문
주어진 조건식(conditional expression)의 평가 결과가 참인 경우 코드 블럭을 실행하며 반복하는데, 조건식이 거짓일 때까지 반복합니다.
3가지의 반복문 for
문, while
문, do…while
문을 제공하며, 그 외에도 for..in
문, ES6에서 새롭게 도입된 for…of
문이 있는데 이는 추후에 설명하겠습니다.
for 문
/*
for (초기화식; 조건식; 증감식) {
조건식이 참인 경우 반복 실행될 문;
}
*/
for (var i = 0; i < 2; i++) {
console.log(i);
}
for (;;) { } // 무한루프
가장 일반적으로 사용되는 반복문으로 조건식이 거짓으로 판별될 때까지 코드 블록을 반복 실행합니다.
실행 순서는 다음과 같습니다.
while 문
var count = 0;
// count가 3보다 작을 때까지 코드 블록을 계속 반복 실행한다.
while (count < 3) {
console.log(count);
count++;
} // 0 1 2
// 무한루프
while (true) { }
주어진 조건식의 평가 결과가 참이면 코드 블록을 계속해서 반복 실행 합니다.
조건문의 평가 결과가 거짓이 되면 실행을 종료하며, 평가 결과가 불리언 값이 아니면 boolean 값으로 강제 변환되어 논리적 참, 거짓을 구별 합니다.
무한루프를 탈출하기 위해서는 코드 블럭 탈출 조건을 if
문에 부여하고 break
문으로 코드 블럭을 탈출하면 됩니다.
do…while 문
var count = 0;
// count가 3보다 작을 때까지 코드 블록을 계속 반복 실행한다.
do {
console.log(count);
count++;
} while (count < 3); // 0 1 2
코드 블록을 실행하고 조건식을 평가하기 때문에 코드 블록은 무조건 1번 이상 실행 됩니다.
break문
레이블 문, 반복문(for, for…in, for…of, while, do…while) 또는 switch 문의 코드 블록을 탈출하며, 이외에 사용하면 SyntaxError(문법 에러)가 발생합니다.
- 레이블 문? 식별자가 붙은 문 - 권장되지 않음
continue문
var string = 'Hello World.';
var count = 0;
// 문자열은 유사배열이므로 for 문으로 순회할 수 있다.
for (var i = 0; i < string.length; i++) {
// 'l'이 아니면 현 지점에서 실행을 중단하고 반복문의 증감식으로 이동한다.
if (string[i] !== 'l') continue;
count++; // continue 문이 실행되면 이 문은 실행되지 않는다.
}
console.log(count); // 3
반복문의 코드 블록 실행을 현 지점에서 중단하고 반복문의 증감식으로 이동합니다.
break
문처럼 반복문을 탈출하지 않습니다.
9. 타입 변환과 단축 평가(Type coercion)
타입 변환이란?
값의 타입은 다른 타입으로 개발자에 의해 의도적으로 변환할 수 있거나 자바스크립트 엔진에 의해 암묵적으로 자동 변환될 수 있습니다.
의도적으로 변환하는 것을 명시적 타입 변환(Explicit coercion) 또는 타입 캐스팅(Type casting)이라 합니다.
자바스크립트는 동적 타입 언어이기 때문에 개발자의 의도와는 상관없이 자바스크립트 엔진에 의해 암묵적으로 타입이 자동 변환되기도 합니다.
이를 암묵적 타입 변환(Implicit coercion) 또는 타입 강제 변환(Type coercion)이라고 합니다.
var x = 10;
// 명시적 타입 변환
var str = x.toString(); // 숫자를 문자열로 타입 캐스팅
console.log(typeof str); // string
// 암묵적 타입 변환
// 숫자 타입 x의 값을 바탕으로 새로운 문자열 타입의 값을 생성해 표현식을 평가
var str = x + '';
console.log(typeof str, str); // string 10
// 변수 x의 값이 변경된 것 아님
console.log(x); // 10
명시적 타입 변환은 타입을 변경하겠다는 개발자의 의지가 코드에 명백히 드러나게 됩니다.
하지만 암묵적 타입 강제 변환은 자바스크립트 엔진에 의해 드러나지 않게 타입이 자동 변환되기 때문에 타입을 변경하겠다는 개발자의 의지가 코드에 명백히 나타나지 않습니다.
타입 변환된 값으로 표현식은 어떻게 평가될 것인지 예측 가능해야 합니다.
만약 예측하지 못하거나 예측한 내용이 결과와 일치하지 않는다면 버그를 생산할 가능성이 높아집니다.
암묵적 타입 변환
그렇다면 암묵적 타입 변환은 어떠한 상황에서 일어나는지 살펴봅시다.
자바스크립트 엔진은 표현식을 평가할 때 문맥, 즉 컨텍스트(Context)에 고려하여 암묵적 타입 변환을 실행합니다.
문자열 타입으로 변환
예시는 다음과 같습니다.
// 숫자 타입
0 + '' // "0"
-0 + '' // "0"
1 + '' // "1"
-1 + '' // "-1"
NaN + '' // "NaN"
Infinity + '' // "Infinity"
-Infinity + '' // "-Infinity"
// 불리언 타입
true + '' // "true"
false + '' // "false"
// null 타입
null + '' // "null"
// undefined 타입
undefined + '' // "undefined"
// 심볼 타입
(Symbol()) + '' // TypeError: Cannot convert a Symbol value to a string
// 객체 타입
({}) + '' // "[object Object]"
Math + '' // "[object Math]"
[] + '' // ""
[10, 20] + '' // "10,20"
(function(){}) + '' // "function(){}"
Array + '' // "function Array() { [native code] }"
연산자 식의 피연산자(피연산자도 표현식이다) 만이 암묵적 타입 변환의 대상이 되는 것은 아닙니다.
컨텍스트에 부합하도록 암묵적 타입 변환을 실행하기에 ES6에서 도입된 템플릿 리터럴의 문자열 인터폴레이션(String Interpolation)은 표현식의 평가 결과를 문자열 타입으로 암묵적 타입 변환 합니다.
console.log(1 + 1 = ${1 + 1}); // "1 + 1 = 2"
숫자 타입으로 변환
// 문자열 타입
+'' // 0
+'0' // 0
+'1' // 1
+'string' // NaN
// 불리언 타입
+true // 1
+false // 0
// null 타입
+null // 0
// undefined 타입
+undefined // NaN
// 심볼 타입
+Symbol() // TypeError: Cannot convert a Symbol value to a number
// 객체 타입
+{} // NaN
+[] // 0
+[10, 20] // NaN
+(function(){}) // NaN
+
단항 연산자는 피연산자가 숫자 타입의 값이 아니면 숫자 타입의 값으로 암묵적 타입 변환을 수행합니다.
빈 문자열(‘’), 빈 배열([]), null, false는 0으로, true는 1로 변환 됩니다.
객체와 빈 배열이 아닌 배열, undefined는 변환되지 않아 NaN이 된다는 것에 주의해야 합니다.
불리언 타입으로 변환
자바스크립트 엔진은 불리언 타입이 아닌 값을 Truthy 값(참으로 인식할 값) 또는 Falsy 값(거짓으로 인식할 값)으로 구분합니다.
즉, Truthy 값은 true
로, Falsy 값은 false
로 변환됩니다.
제어문의 조건식과 같이 불리언 값으로 평가되어야 할 컨텍스트에서 false
로 평가되는 Falsy 값은 다음과 같습니다.
false
, undefined
, null
, 0
, -0
, NaN
, ’’ (빈문자열)
명시적 타입 변환
래퍼 객체를 생성하기 위해 사용하는 래퍼 객체 생성자 함수를 new 연산자 없이 호출하는 방법과 자바스크립트에서 제공하는 빌트인 메소드를 사용하는 방법, 그리고 앞에서 살펴본 암묵적 타입 변환을 이용하는 방법이 있습니다.
여러 방법에 대해 간단하게 알아보겠습니다.
문자열 타입으로 변환
- String 생성자 함수를 new 연산자 없이 호출하는 방법 →
console.log(String(1));
- Object.prototype.toString 메소드를 사용하는 방법 →
console.log((1).toString());
- 문자열 연결 연산자를 이용하는 방법 →
console.log(1 + '');
숫자 타입으로 변환
- Number 생성자 함수를 new 연산자 없이 호출하는 방법 →
console.log(Number('0'));
- parseInt, parseFloat 함수를 사용하는 방법(문자열만 변환 가능) →
console.log(parseInt('0'));
+
단항 연결 연산자를 이용하는 방법 →console.log(+'0');
*
산술 연산자를 이용하는 방법 →console.log('0' * 1);
불리언 타입으로 변환
- Boolean 생성자 함수를 new 연산자 없이 호출하는 방법 →
console.log(Boolean('x')); // true
!
부정 논리 연산자를 두 번 사용하는 방법 →console.log(!!'x'); // true
단축 평가
논리곱 연산자 &&
와 논리합 연산자 ||
는 이와 같이 논리 평가를 결정한 피연산자의 평가 결과를 그대로 반환 합니다.
이를 단축 평가(Short-Circuit evaluation) 라 부르며 아래의 규칙을 따릅니다.
단축 평가 표현식 | 평가 결과 |
---|---|
true || anything | true |
false || anything | anything |
true && anything | anything |
false && anything | false |
'Cat' && 'Dog' // “Dog”
논리곱 연산자 &&
는 두개의 피연산자가 모두 true
로 평가될 때 true
를 반환 합니다. (오른쪽 → 왼쪽으로 평가)
&&
는 논리 연산의 결과를 결정한 두번째 피연산자의 평가 결과 즉, 문자열 ‘Dog’를 그대로 반환 합니다.
'Cat' || 'Dog' // 'Cat'
논리합 연산자 ||
는 두개의 피연산자 중 하나만 true
로 평가되어도 true
를 반환 합니다.
논리합 연산자 ||
는 논리 연산의 결과를 결정한 첫번째 피연산자의 평가 결과 즉, 문자열 ‘Cat’를 그대로 반환 합니다.
여기까지 JavaScript lesson 7~9에 해당되는 연산자, 제어문, 타입 변환에 대해 알아보았습니다.
상세한 예시와 설명은 원본 글 참고 부탁드립니다 ㅎㅎ!