목표
※ 5장 표현식과 문은 생략
6장 데이터 타입
- 자바스크립트의 모든 값은 데이터 타입을 갖는다.
- ES6를 기준으로 7개의 데이터 타입이 존재하는데, 이 7개의 데이터 타입은 원시 타입과 객체 타입으로 구분된다.
const numberOne = 1;
const stringOne = "1";
- 예를 들어, 숫자 타입의 값 1과 문자 타입의 값 "1"은 비슷해 보이지만 생성한 목적과 용도가 다르다.
- 또한, 확보해야 할 메모리 공간의 크기도 다르고 메모리에 저장되는 2진수도 다르다.
- 이처럼, 개발자는 명확한 의도를 가지고 타입을 구별해야 한다.
6-1. 숫자(Number) 타입
- C와 Java는 정수와 실수를 구분해서 int, long, float, double 등과 같은 다양한 숫자 타입을 제공한다.
- 하지만, 자바스크립트는 하나의 숫자 타입 Number 만을 제공한다.
- 자바스크립트 표준 사양인 ECMAScript에 따르면 숫자 타입의 값은 배정밀도 64비트 부동소수점 형식을 따른다. 즉, 모든 수를 실수로 처리한다. (정수를 위한 데이터 타입이 존재하지 않는다.)
var integer = 10;
var double = 10.12;
var negative = -10;
console.log(typeof integer);
console.log(typeof double);
console.log(typeof negative);
"number"
"number"
"number"
- 모든 수를 실수로 처리하므로 다음과 같은 결과도 가능하다.
console.log(1 === 1.0);
console.log(10 === 10.000);
true
true
- 자바스크립트로 정수끼리 나누다보면 실수가 출력되는 경우도 모든 수를 실수로 처리하기 때문이다.
console.log(4 / 2);
console.log(3 / 2);
2
1.5
- 자바스크립트는 2진수, 8진수, 16진수를 표현하기 위한 데이터 타입을 제공하지 않는다. 이들 값을 참조하면 모두 10진수로 해석한다.
- 다음 코드는 정수 65를 각각 2진수, 8진수, 16진수로 나타낸 값이다.
var binary = 0b01000001;
var octal = 0o101;
var hex = 0x41;
console.log(binary === octal);
console.log(octal === hex);
true
true
- 숫자 타입은 추가적으로 Infinity(양의 무한대), -Infinity(음의 무한대), NaN(산술 연산 불가) 세 가지 값을 표현할 수 있다.
console.log(10 / 0);
console.log(10 / -0);
console.log(10 * "string");
Infinity
-Infinity
NaN
6-2. 문자열(String) 타입
- C는 문자열 타입을 제공하지 않고 문자를 배열로 표현하고 Java는 문자열을 객체로 표현한다.
- 자바스크립트의 문자열(String)은 원시 타입이며 변경 불가능한 값이다. 즉, 문자열을 생성하면 변경할 수 없다.
- 문자열은 작은따옴표(''), 큰 따옴표("") 를 사용해 문자열을 표현한다.
var string;
string = 'string';
string = "string";
[참고] 템플릿 리터럴
- ES6부터 새로운 문자열 표기법이 등장했는데 일반 문자열과 비슷해 보이지만 따옴표 대신 백틱(``)을 사용한다.
(1) 멀티라인 문자열
- 일반 문자열에서는 줄바꿈(개행)이 허용되지 않는다.
var str = "Hello
World."
- 따라서, 일반 문자열 내에서 줄바꿈을 표현하려면 백슬래시(\)로 시작하는 이스케이프 시퀀스를 사용해야 한다.
- 예를 들어, 줄바꿈(\n)과 들여쓰기(\t)가 적용된 HTML 문자열은 다음과 같다.
var template = "<table>\n\t<tr>\n\t<td>내용</td></tr></table>";
- 줄바꿈과 들여쓰기가 눈에 잘 들어오지 않고 복잡해 보인다.
- 하지만, 템플릿 리터럴 즉, 백틱을 사용하면 줄바꿈과 들여쓰기가 눈에 확 들어와 가독성이 좋아진다.
var tamplate = `
<table>
<tr>
<td>내용</td>
</tr>
</table>
`;
(2) 표현식 삽입
- 문자열은 연산자 +를 사용해서 서로 연결할 수 있다.
var food = "hamburger";
var evaluation = "tasty";
console.log(food + " is " + evaluation);
"hamburger is tasty"
- 템플릿 리터럴에서는 문자열 연산자 보다 가독성이 좋고 간편하게 문자열을 조합할 수 있다.
- 이 때, 표현식을 삽입하려면 ${ } 으로 표현식을 감싼다.
var food = "hamburger";
var evaluation = "tasty";
console.log(`${food} is ${evaluation}`);
"hamburger is tasty"
- 참고로 표현식의 평가 결과는 문자열로 강제로 타입이 변환되어 삽입된다.
6-4. 불리언(Boolean) 타입
- 불리언(Boolean) 타입의 값은 다른 프로그래밍 언어와 마찬가지로 true와 false가 존재한다.
- 주로 조건문에서 사용된다.
var number1 = 3 * 4;
var number2 = 4 * 3;
var number3 = 3 + 7;
console.log(number1 === number2);
console.log(number1 === number3);
true
false
6-5. undefined 타입
- 4장 변수에서 var 키워드로 선언한 변수는 암묵적으로 undefined 가 초기화 된다는 것을 확인했다.
- 즉, undefined 가 반환된다면 변수 선언 이후 값이 할당된 적이 없는 즉, 초기화되지 않은 변수란 것을 알 수 있다.
- 또한, 자바스크립트 엔진이 변수를 초기화하는 데 사용하는 undefined 를 개발자가 의도적으로 변수에 할당한다면 본래 취지와 어긋나 혼란을 줄 수 있다.
🤔 의문
-
그렇다면 변수에 값이 없다는 것을 명시하고 싶을 때에는 어떻게 해야 할까?
그런 경우에는 undefined 대신 null을 할당하면 된다.
6-6. null 타입
- null은 변수에 값이 없다는 것을 의도적으로 명시할 때 사용한다.
- 즉, 변수에 null을 할당한다는 것은 변수가 이전에 참조했던 값을 더 이상 참조하지 않겠다는 것이다.
var food = "hamburger";
food = null;
💡 주의
-
자바스크립트 엔진은 대소문자를 구분하므로 null 이외의 값 Null, NULL 등 과는 다르다.
6-7. 심벌(Symbol) 타입
- 심벌(Symbol)은 ES6에서 추가된 타입으로 변경 불가능한 원시 타입의 값이다.
- 심벌 값은 다른 값과 중복되지 않는 유일한 값이다.
- 주로 이름이 충돌할 위험이 없는 객체의 유일한 프로퍼티 키를 만들기 위해 사용한다.
var key = Symbol('key');
var obj = {};
obj[key] = 'value';
console.log(obj[key]);
value
- 심벌은 Symbol 함수를 호출해 사용한다.
- 이때 생성한 심벌값은 외부에 노출되지 않으며, 다른 값과 절대 중복되지 않는 유일무이한 값이다.
6-8. 객체(Object) 타입
- 객체, 함수, 배열 등이 해당한다.
- 위에서 살펴보았던 템플릿 리터럴을 제외하고는 6가지 데이터 타입 이외의 값들은 모두 객체타입이다.
6-9. 데이터 타입은 왜 필요한 것일까?
🤔 의문
-
변수에 값을 할당하면 어떠한 데이터 타입이든 똑같이 2진수로 저장되는데 굳이 데이터 타입을 나누는 이유는 무엇일까?
크게 세 가지 이유가 존재한다.
6-9-1. 메모리 공간의 확보와 참조
- 값을 할당하면 메모리 공간을 확보한다. 하지만, 무턱대고 너무 적거나 많은 공간을 확보하면 할당하고자 하는 값을 완벽히 할당하지 못하거나 메모리 공간을 낭비할 것이다.
- 따라서, 몇 바이트의 메모리 공간을 확보해야 낭비와 손실 없이 값을 정할 수 있을지에 대한 기준이 바로 데이터 타입이다.
var number = 10;
- 위 코드가 실행되면 컴퓨터는 숫자 10을 저장하기 위해 메모리 공간을 확보한 뒤 그 공간에 10을 2진수 형태로 저장한다.
- 이러한 처리를 하려면 메모리 공간의 크기를 알아야 한다.
- 자바스크립트 엔진은 변수에 할당되는 값의 데이터 타입에 따라 메모리 공간의 크기를 결정하는데, 위의 예에서는 숫자 10을 저장하기 위해 8바이트의 메모리 공간을 확보한다.
❗️ 참고
-
ECMAScript 사양은 문자열과 숫자 타입 외에는 명시적으로 규정하고 있지는 않다. 따라서, 문자열과 숫자 타입 외에는 자바스크립트 엔진 제조사의 구현에 따라 확보되는 메모리 크기가 다를 수 있다.
6-9-2. 메모리 공간의 참조
- 이번에는 값을 참조하는 경우를 생각해보자.
- 식별자 number를 통해 값 10이 저장되어 있는 메모리 주소를 알 수 있다. 즉, 값 10이 저장되어 있는 메모리 주소의 처음 메모리 셀의 주소를 알 수 있다.
- 이제 자바스크립트 엔진이 메모리 공간의 크기 즉, 몇 개의 메모리 셀을 읽어야 할지 결정해야 하는데 이 역시 값의 데이터 타입을 통해 결정한다.
- 위의 예에서는 처음 메모리 셀의 주소인 0x000000FA에서 8개의 메모리 셀을 읽게되는 것이다.
6-9-3. 데이터 타입에 의한 값의 해석
- 메모리 공간에 저장되어 있는 2진수로 된 값을 어떻게 해석하는지도 데이터 타입에 따라 결정된다.
- 예를 들어, 메모리에 저장된 값 0100 0001을 숫자로 해석하면 65지만 문자로 해석하면 A가 된다.
지금까지의 설명을 정리해보자면 다음과 같다.
데이터 타입이 필요한 이유
-
값을 저장할 때 필요한 메모리 공간의 크기를 정하기 위해
-
값을 참조할 때 한 번에 읽어들일 메모리 공간의 크기를 정하기 위해
-
메모리에 저장된 2진수의 값을 어떻게 해석할지 결정하기 위해
※ 6-10 동적 타이핑은 생략
7장 연산자
const operation = 10 + 20;
- 위 표현식은 피연산자(10과 20)와 연산자(+)를 통해 연산을 수행해 하나의 값을 만든다.
- 즉, 피연산자는 연산의 대상이 되는 값으로 평가될 수 있어야 하며 연산자는 값으로 표현된 피연산자를 연산해 새로운 값을 만든다.
- 자바스크립트에서 연산자는 산술, 할당, 비교, 논리, 타입, 지수 연산 등이 있다.
7-1. 산술 연산자
- 산술 연산자는 피연산자를 대상으로 수학적 계산을 수행해 새로운 값을 만든다.
- 이 때, 산술이 불가능 한 경우 NaN을 리턴한다.
- 산술 연산자는 피연산자의 개수에 따라 이항 산술 연산자와 단항 산술 연산자로 구분된다.
7-1-1. 이항(binary) 산술 연산자
- 이항 산술 연산자는 2개의 피연산자를 산술 연산하여 숫자값을 반환한다.
console.log(5 + 2);
console.log(5 - 2);
console.log(5 * 2);
console.log(5 / 2);
console.log(5 % 2);
7
3
10
2.5
1
7-1-2. 단항(unary) 산술 연산자
- 단항 산술 연산자는 1개의 피연산자를 산술 연산하여 숫자값을 반환한다.
var number = 1;
number++;
console.log(number);
number--;
console.log(number);
2
1
- 위 코드의 증가(++)연산자와 감소(--)연산자는 피연산자의 값을 변경하는 암묵적 할당이 발생한다.
예) number = number + 1;
💡 주의
-
증가 연산자와 감소 연산자는 위치에 따라 값이 달라지므로 주의해야 한다.
var number = 5, result;
result = number++;
console.log(`${result}, ${number}`);
result = ++number;
console.log(`${result}, ${number}`);
5, 6
7, 7
- 후위 증가 연산자는 먼저 연산을 수행한 후 피연산자의 값을 증가시킨다.
- 위의 예에서는 number 변수의 값을 result 변수에 할당 한 뒤 number 변수의 값을 증가시키므로 result 변수의 값은 5, number 변수의 값은 6이된다.
- 전위 증가 연산자는 피연산자의 값을 먼저 증가 시킨 뒤 연산을 수행한다.
- 위의 예에서는 number 변수의 값을 먼저 증가시킨 뒤 result 변수에 값을 할당하므로 result 변수의 값과 number의 값이 7이된다.
※ +와 - 단항 연산자는 생략
7-1-3. 문자열 산술 연산자
- "+" 연산자는 피연산자 중 하나 이상이 문자열인 경우 문자열 연결 연산자로 동작한다.
- 그외 경우에는 산술 연산자로 동작한다.
console.log("1" + 1);
console.log(1 + "1");
"11"
"11"
console.log(1 + 1);
console.log(1 + true);
console.log(1 + false);
console.log(1 + null);
console.log(1 + undefined);
2
2
1
1
NaN
- 위에서 1 + true 를 보면 자바스크립트 엔진이 암묵적으로 불리언(Boolean) 타입의 값인 true를 숫자 타입인 1로 강제로 변환 후 연산을 수행한 것을 확인할 수 있다.
- 이를 암묵적 타입 변환(implicit coercion) 또는 타입 강제 변환(type coercion)이라고 한다.
7-2. 할당 연산자
- 할당 연산자(Assignment Operator)는 우항에 있는 피연산자의 평가 결과를 좌항에 있는 변수에 할당한다.
var number = 10;
number += 5;
console.log(number);
number -= 5;
console.log(number);
number *= 5;
console.log(number);
number /= 5;
console.log(number);
number %= 5;
console.log(number);
number += "10";
console.log(number);
15
10
50
10
0
"010"
7-3. 비교 연산자
- 비교 연산자(Comparison Operator)는 좌항과 우항의 피연산자를 비교한 다음 그 결과 값을 불리언 값으로 반환한다.
- 주로 if문 같은 조건문에 많이 쓰인다.
7-3-1. 동등 비교 연산자, 일치 비교 연산자
- 동등 비교 연산자(==) 와 일치 비교 연산자(===) 의 차이는 피연산자들의 값은 물론 타입까지 비교하는지에 따라 구분된다.
console.log(5 == "5");
true
- 동등 비교 연산자는 피연산자를 비교할 때 암묵적 타입 변환을 통해 타입을 일치 시킨 후 같은 값인지 비교한다. 따라서, 타입이 다르더라도 같은 값이기만 한다면 true를 반환한다.
- 하지만, 이러한 기능을 가지고 있는 동등 비교 연산자는 예측하기 어려운 단점이 존재한다.
console.log(5 === "5")
false
- 일치 비교 연산자는 암묵적 타입 변환을 거치지 않고 값과 타입이 모두 같은 경우에만 true를 반환한다. 따라서, 일치 비교 연산자는 예측하기 쉬워진다.
7-3-2. 대소 관계 비교 연산자
- 대소 관계 비교 연산자는 피연산자의 크기를 비교해 불리언 값을 리턴한다.
console.log(5 > 0);
console.log(5 < 0);
console.log(5 <= 5);
console.log(5 >= 5);
true
false
true
true
7-4. 삼항 조건 연산자
- 삼항 조건 연산자(ternary operator)는 조건식의 평가 결과에 따라 반환할 값을 결정한다.
조건식 ? 조건식이 true일 때 반환할 값 : 조건식이 false일 때 반환할 값;
- 삼항 연산자는 첫 번째 피연산자가 true이면 두 번째 피연산자가 반환되고 false이면 세 번째 피연산자가 반환된다.
var number = 2;
var isEvenNumber = number % 2 === 0 ? true : false;
var isOddNumberToString = !(number % 2 === 0) ? "짝수입니다." : "홀수입니다.";
console.log(isEvenNumber);
console.log(isOddNumberToString);
true
"홀수입니다."
- 삼항 조건 연산자는 if-else 문과 굉장히 유사하다.
- 조건에 따라 어떤 값을 결정해야 한다면 삼항 조건 연산자를 쓰고 조건에 따라 수행해야 할 문이 여러 개라면 if-else문을 수행하는 것이 가독성 측면에서 더 좋다.
7-5. 논리 연산자
- 대표적인 논리 연산자(Logical Operator)에는 ||(OR), &&(AND), !(NOT)가 있다.
var number1 = 1;
var number2 = 2;
function evalEvenNumber(number) {
return number % 2 === 0 ? true : false
}
console.log(evalEvenNumber(number1) || evalEvenNumber(number2));
console.log(evalEvenNumber(number1) && evalEvenNumber(number2));
console.log(!evalEvenNumber(number1));
console.log(!evalEvenNumber(number2));
true
false
true
false
- 논리합(||) 연산자는 피연산자 둘 중 하나라도 참이면 true를 반환한다.
- 논리곱(&&) 연산자는 피연산자 둘 다 모두 참일 때 true를 반환한다.
- 부정(!) 연산자는 피연산자의 결과값이 참이면 false를 거짓이면 true를 반환한다.
※ 7-6 쉼표 연산자, 7-7 그룹 연산자는 생략
7-8. typeof 연산자
- typeof 연산자는 데이터의 타입을 문자열로 반환한다.
- 반환하는 값으로는 string, number, boolean, undefined, symbol, object, function 중 하나이다.
console.log(typeof "string");
console.log(typeof 2);
console.log(typeof true);
console.log(typeof undefined);
console.log(typeof Symbol());
console.log(typeof [1, 2, 3]);
console.log(typeof { number: 1, string: "str" });
console.log(typeof function() {});
console.log("=========");
console.log(typeof null);
- 위의 코드에서 대부분 typeof가 반환하는 값으로 예측이 가능하다.
- 하지만, 맨 마지막 null을 보면 typeof가 반환하는 값으로 "null"이 없어 예측이 불가능하다.
- 실제로 값을 찍어보면 "object"로 찍히는 것을 알 수 있다.
- 이것은 자바스크립트 첫 번째 버전의 버그라고 하는데 이는 MDN - typeof 에서 확인할 수 있다.
- 따라서, 값이 null 타입인지 확인하기 위해서는 일치 비교 연산자(===)를 사용해야 한다.
7-9. 지수 연산자
- ES7에서 도입된 지수 연산자(Exponent Operator)는 좌항의 피연산자를 밑으로 우항의 피연산자를 지수로 거듭제곱하여 값을 리턴한다.
- 참고로 지수 연산자가 도입되기 전까지 Math.pow 메서드를 사용했다.
console.log(2 ** 2);
console.log(2 ** 2 ** 2);
4
16
💡 주의
-
음수를 거듭제곱하기 위해서는 밑에 해당하는 좌항의 피연산자를 괄호로 묶어줘야 한다. 묶어주지 않으면 SyntaxError 발생한다.
console.log(-5 ** 2);
console.log((-5) ** 2);
Uncaught SyntaxError
25