본문 바로가기

2022-2 웹개발 스터디

[모던 JS] CH6 데이터 타입, CH7 연산자

CH6. 데이터 타입

- 데이터 타입은 원시 타입과 객체 타입으로 분류할 수 있음

6.1 숫자타입

- JS는 하나의 숫자 타입만 존재함

- 모든 수를 실수로 처리하며 정수만 표현하기 위한 데이터 타입이 존재하지 않음

var integer = 10;
var double = 10.12;
var negative = -20;

- 2진수, 8진수, 16진수를 표현하기 위한 데이터 타입을 제공하지 않기 때문에 모두 10진수로 해석됨

var binary = 0b01000001;  // 2진수
var octal = 0o101;  // 8진수
var hex = 0x41;  // 16진수

console.log(binary); // 65
console.log(octal); // 65
console.log(hex); // 65

console.log(binary == octal); // true
console.log(octal == hex); // true

 

!

- 정수로 표시된다 해도 사실은 실수라는 것을 의미

- 정수로 표시되는 수끼리 나누더라도 실수가 나올 수 있음

console.log(1 == 1.0); // true
console.log(4 / 2); // 2
console.log(3 / 2); // 1.5

 

!! 

숫자 타입은 추가적으로 세 가지 특별한 값도 표현할 수 있음

- 양의 무한대

- 음의 무한대

- 산술 연산 불가 (NaN)

console.log(10 / 0); // Infinity
console.log(10 / -0); // -Infinity
console.log(1 * 'String'); // NaN

 

!!! NaN을 NAN Nan nan과 같이 표현하면 에러가 발생함

// 대소문자 구별
var x = nan; // ReferenceError

6.2 문자열 타입

- 작은따옴표, 큰따옴표, 백틱으로 텍스트를 감쌈

- 일반적인 표기법은 작은따옴표

var string;
string = 'hi';
string = "hi";
string = `hi`;

6.3 템플릿 리터럴

- `을 사용해 표현

var template = `Template literal`;
console.log(template);

6.3.1 멀티라인 문자열

- 일반 문자열 내에서는 줄바꿈이 허용되지 않음

- 이런 경우, 이스케이프 시퀀스를 사용해야 함

- 일반 문자열과 달리 템플릿 리터럴 내에서는 이스케이프 시퀀스를 사용하지 않고도 줄바꿈이 허용되며, 모든 공백이 적용

var template = `Hello
world`;

6.3.2 표현식 삽입

- 표현식 삽입을 통해 간단히 문자열 삽입 가능

- 가독성 좋고 간편하게 문자열 조합 가능

- ${}으로 표현식을 감싸는데, 문자열이 아니더라도 문자열로 타입이 강제변환되어 삽입됨

- 반드시 템플릿 리터럴 안에서 사용해야 함 (템플릿 리터럴이 아닌 일반 문자열에서 표현식 삽입은 문자열로 취급됨)

console.log(`1 + 2 = ${1 + 2}`); // 1 + 2 = 3

console.log('1 + 2 = ${1 + 2}'); // 1 + 2 = ${1 + 2}

6.4 불리언타입

- 조건문에서 자주 사용

var foo = true;
console.log(foo); // true

foo = false;
console.log(foo); // false

6.5 undefined 타입

- undefined 타입의 값은 undefined가 유일

- 개발자가 의도적으로 할당하기 위한 값이 아닌 자바스크립트 엔진이 변수를 초기화할 때 사용하는 값

- 개발자가 의도적으로 undefined를 변수에 할당한다면 혼란을 줄 수 있으므로 권장하지 않음

: 변수에 값이 없다는 것을 명시하고 싶다면? null을 할당

var foo;
console.log(foo); // undefined

6.6 null 타입

- null 타입의 값은 null이 유일

- 변수에 값이 없다는 것을 의도적으로 명시할 때 사용

var foo = 'Lee';

// 이전 참조 제거
foo = null

- 함수가 유효한 값을 반환할 수 없는 경우 명시적으로 null을 반환하기도 한다

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
    var element = document.querySelector('.myClass');
    
    // html 문서에 myClass 클래스를 갖는 요소가 없다면 null 반환
    console.lig(element); // null
    </script>
</body>
</html>

6.7 심벌 타입

- 변경 불가능한 원시 타입의 값

- 이름이 충돌할 위험이 없는 객체의 유일할 프로퍼티 키를 만들기 위해 사용

- 생성된 심벌값은 외부에 노출되지 않으며, 다른 값과 절대 중복되지 않는 유일무이한 값

var key = Sysbol('key');
console.lig(typeof key); // symbol

var obj = {};
obj[key] = 'value';
console.log(obj[key]);

6.8 객체 타입

- 11장에서 나옴

- 중요한 것은 자바스크립트는 객체 기반의 언어이며, 자바스크립트를 이루고 있는 거의 모든 것이 객체임

6.9 데이터 타입의 필요성

- 값을 저장할 때 확보해야 하는 메모리 공간의 크기를 결정하기 위해

- 값을 참조할 때 한 번에 읽어 들여야 할 메모리 공간의 크기를 결정하기 위해

- 메모리에서 읽어 들인 2진수를 어떻게 해석할지 결정하기 위해

6.10 동적 타이핑

6.10.1 동적 타입 언어와 정적 타입 언어

! 정적 타입 언어

: 변수를 선언할 때 변수에 할당할 수 있는 값의 종류를 사전에 선언해야 함

char c;
int num;

: 변수의 타입 변경 불가능, 선언한 타입에 맞는 값만 할당 가능

 

! 자바스크립트는 정적 타입 언어와 다르게 타입을 선언하지 않음

: var, let, const 키워드를 사용해 변수를 선언함

: 어떠한 데이터 값이라도 자유롭게 할당할 수 있음

: typeof 연산자로 변수의 데이터 타입을 조사할 수 있음

: 선언이 아닌 할당에 의해 타입이 결정됨 (타입 추론)

: 재할당에 의해 언제든지 변수의 타입이 동적으로 변할 수 있음

: 동적 타입 언어

var foo;
console.log(typeof foo); // undefined

foo = 3;
console.log(typeof foo); // number

foo = 'Hello';
console.log(typeof foo); // string

foo = null;
console.log(typeof foo); // object

foo = Symbol();
console.log(typeof foo); // symbol

foo = {};
console.log(typeof foo); // object

foo = [];
console.log(typeof foo); // object

foo = function() {};
console.log(typeof foo); // function

6.10.2 동적 타입 언어와 변수

! 단점

: 언제든지 변경될 수 있기 때문에 복잡한 프로그램에서는 변화하는 변수 값 추적하기 어려움

: 변수의 타입이 고정되어 있지 않아 언제든지 변경될 수 있어 변수의 값을 확인하기 전에는 타입을 확신하기 어려움

: 개발자의 의도와 상관없이 자바스크립트 엔진에 의해 암묵적으로 타입이 자동 변환되기도 함

: 유연성은 높지만, 신뢰성이 떨어짐 

CH7. 연산자

7.1 산술연산자

- 산술 연산이 불가능한 경우 NaN 반환

7.1.1 이항 산술 연산자

7.1.2 단항 산술 연산자

이항 산술 연산자와 달리 증가/감소 연산자는 피연산자의 값을 변경하는 부수 효과가 있음

즉, 암묵적 할당이 이뤄지는 것

var x = 1;

x++;
console.log(x); // 2

x--;
console.log(x); // 1

7.1.3 문자열 연결 연산자

+ 연산자는 피연산자 중 하나 이상이 문자열인 경우 문자열 연결 연산자로 동작

'1' + 2; // '12'
12 + 45 + '67'; // '5767'

// true는 1, false는 0으로 타입 변환
1 + true; // 2
1 + false; // 1

// null은 0으로 타입 변환
1 + null; // 1

// undefined는 숫자로 타입 변환되지 않음
+undefined; // NaN
1 + undefined; // NaN

7.2 할당 연산자

7.3 비교 연산자

- 좌항과 우항의 피연산자를 비교한 다음 그 결과를 불리언 값으로 반환함

- 조건문이나 반복문에서 주로 사용

7.3.1 동등/일치 비교 연산자

- 동등 비교 연산자는 느슨한 비교를 하지만,일치 비교 연산자는 엄격한 비교를 함

- 동등 비교 연산자는 예측하기 어려운 결과를 만들어내므로 일치 비교 연산자를 사용하는 편이 좋음

5 == 5; // true
5 == '5' // true

// 결과를 예측하기 어려움
'0' == ''; // false
0 == ''; // true
0 == '0' // true

false == 'false'; // false
false == '0'; // true
false == null; // false
false == undefined; // false

 

- 일치 비교 연산자는 암묵적 타입 변환을 하지 않고 값을 비교하므로 예측하기 쉬움

5 === 5; // true
5 === '5' // false

// 주의!
// NaN은 자신과 일치하지 않는 유일한 값
NaN === NaN; // false

// NaN인지 조사하는 함수 Number.isNaN
Number.isNaN(NaN); // true
Number.isNaN(10); // false

// ㅈㅇ!
// 양의 0과 음의 0 비교
0 === -0; // true
0 == -0; // true

 

- 부동등 비교 연산자(!=)와 불일치 비교 연산자(!==)는 각자 동등 비교와 일치 비교 연산자의 반대 개념

// 부동등 비교
5 != 8; // true
5 != 5; // false
5 != '5'; // false

// 불일치 비교
5 !== 8; // true
5 !== 5; // false
5 !== '5'; // true

7.3.2 대소 관계 비교 연산자

7.4 삼항 조건 연산자

- 조건식의 평가 결과에 따라 반환할 값을 결정

- 조건에 따라 if...else 문보다 삼항 조건 연산자 표현식을 사용하는 편이 유리할 수 있음

var x = 2;
var res = x % 2? '홀수' : '짝수';

console.log(res); // 짝수

7.5 논리 연산자

- 논리 부정 연산자는 언제나 불리언 값을 반환함

- 피연산자가 반드시 불리언일 필요는 없음, 만약 피연산자가 불리언 값이 아니면 암묵적 타입 변환

!0; // true
!'Hello'; // false

 

- 논리합 또는 논리곱 연산자 표현식의 평가 결과는 불리언 값이 아닐 수도 있음

// 단축 평가 -> 9.4절
'Cat' && 'Dog'; // 'Dog'

7.6 쉼표 연산자

- 왼쪽 피연산자부터 차례대로 피연산자를 평가하고

  마지막 피연산자의 평가가 끝나면 마지막 피연산자의 평가 결과를 반환

var x, y, z;

x = 1, y = 2, z = 3; // 3

7.7 그룹 연산자

- 연산자 우선순위가 가장 높음

10 * 2 + 3; // 23
10 * (2 + 3); // 50

7.8 typeof 연산자

- string, number, boolean, undefined, symbol, object, function 중 하나를 반환함

- null을 반환하는 경우는 없음

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 function () {} // function

 

! ㅈㅇ
값이 null 타입인지 확인할 때는 typeof 연산자를 사용하지 말고 일치 연산자(===) 사용해야 함

typeof null // object

var foo = null;

typeof foo === null; // false
foo === null; // true

 

!! ㅈㅇ

선언하지 않은 식별자를 typeof 연산자로 연산해보면 ReferenceError가 발생하지 않고 undefined를 반환함

typeof undeclared; // undefined

7.9 지수 연산자

2 ** 2; // 4
2 ** 0; // 1
2 ** -2; // 0.25

// 지수연산자 도입 이전
Math.pow(2, 2) // 4
Math.pow(2, 0) // 1
Math.pow(2, -2) // 0.25

// 음수를 거듭제곱의 밑으로 사용하는 경우, 괄호로 묶어야 함
(-5) ** 2; // 25

 

- 다른 산술 연산자와 마찬가지로 할당 연산자와 함께 사용 가능

- 이항 연산자 중 우선순위가 가장 높음

var num = 5;
num ** 2; // 25

7.10 그 외의 연산자

7.11 연산자의 부수 효과

- 부수 효과가 있는 연산자는 할당 연산자(=), 증가/감소 연산자 (++/--), delete 연산자

var x;

x = 1;
console.log(x); // 1

x ++;
console.log(x); // 2

var o = {a : 1};
// delete 연산자는 객체의 프로퍼티를 삭제하는 부수 효과
delete o.a;
console.log(o); // {}

7.12 연산자 우선순위

- 우선순위가 높을수록 먼저 실행됨

-  실수하기 쉬우므로 그룹 연산자를 사용해서 명시적으로 조절하는 것이 좋음

7.13 연산자 결합 순서