6장 - 데이터 타입
데이터 타입은 값의 종류를 말한다.
자바스크립트(ES6)는 7개의 데이터 타입을 제공
원시 타입
숫자 타입(number) → 숫자, 정수와 실수 구분 없이 하나의 숫자 타입만 존재
문자열 타입(string) → 문자열
불리언 타입(boolean) → 논리적 참과 거짓
undefined 타입 → var 키워드로 선언된 변수에 암묵적으로 할당되는 값
null 타입 → 값이 없다는 것을 의도적으로 명시할 때 사용하는 값
심벌 타입(symbol) → ES6에서 추가된 7번째 타입
객체 타입
객체, 함수, 배열 등
숫자 타입
자바스크립트는 독특하게 하나의 숫자 타입만 존재한다.
ECMAScript 사양에 따르면 숫자 타입의 값은 배정밀도 64비트 부동소수점 형식을 따름
→ 모든 수를 실수로 처리, 정수만 표현하기 위한 데이터 타입이 별도로 존재하지 않는다.
→ 정수로 표시되는 수끼리 나누더라도 실수가 나올 수 있다.
숫자 타입은 추가적으로 세 가지 특별한 값도 표현할 수 있다.
- Infinity: 양의 무한대
- -Infinity: 음의 무한대
- NaN: 산술 연산 불가(not-a-number)
자바스크립트는 대소문자를 구별하므로 NaN을 다른 대소문자로 표현하면 안된다.
문자열 타입
문자열은 0개 이상의 16비트 유니코드 문자(UTF-16)의 집합으로 전 세계 대부분의 문자를 표현할 수 있다.
문자열은 작은따옴표(가장 일반적인 표기법), 큰따옴표, 백틱으로 텍스트를 감싼다.
자바스크립트의 문자열은 원시 타입이며, 변경 불가능한 값
→ 문자열이 생성되면 그 문자열을 변경할 수 없다.
템플릿 리터럴
ES6부터 템플릿 리터럴이라고 하는 새로운 문자열 표기법이 도입
멀티라인 문자열, 표현식 삽입, 태그드 템플릿 등 편리한 문자열 처리 기능을 제공
멀티라인 문자열
일반 문자열 내에서는 줄바꿈(개행)이 허용되지 않는다.
일반 문자열 내에서 줄바꿈 등의 공백을 표현하려면 백슬래시(\)로 시작하는 이스케이프 시퀀스를 사용해야 한다.
일반 문자열과 달리 템플릿 리터럴 내에서는 이스케이프 시퀀스를 사용하지 않고도 줄바꿈이 허용되며, 모든 공백도 있는 그대로 적용된다.
라인 피드와 캐리지 리턴
개행 문자에는 라인 피드(\n)와 캐리지 리턴(\r)이 있다.
라인 피드: 커서를 정지한 상태에서 종이를 한 줄 올리는 것
캐리지 리턴: 종이를 움직이지 않고 커서를 맨 앞줄로 이동하는 것
자바스크립트에서 캐리지 리턴으로 개행하는 경우는 거의 없고 일반적으로 라인 피드를 사용해 개행한다.
표현식 삽입
문자열은 문자열 연산자 +를 사용해 연결 가능
템플릿 리터럴 내에서는 표현식 삽입을 통해 간단히 문자열을 삽입할 수 있다.
표현식을 삽입하려면 ${ }으로 표현식을 감싼다.
→ 표현식의 평가 결과가 문자열이 아니더라도 문자열로 타입이 강제로 변환되어 삽입된다.
→ 표현식 삽입은 반드시 템플릿 리터럴 내에서 사용해야한다.
불리언 타입
불리언 타입의 값은 논리적 참, 거짓을 나타내는 true와 false뿐
undefined 타입
var 키워드로 선언한 변수는 암묵적으로 undefined로 초기화
변수를 선언한 이후 값을 할당하지 않은 변수를 참조하면 undefined 반환
undefined는 개발자가 의도적으로 할당하지 않은 값이 아니라 자바스크립트 엔진이 변수를 초기화할 때 사용하는 값
선언과 정의
ECMAScript 사양에서 변수는 ‘선언한다’라고 표현하고, 함수는 ‘정의한다’라고 표현
null 타입
자바스크립트는 대소문자를 구별하므로 null은 Null, NULL과 다르다.
프로그래밍 언어에서 null은 변수에 값이 없다는 것을 의도적으로 명시(의도적 부재)할 때 사용
→ 변수에 null을 할당하는 것은 변수가 이전에 참조하던 값을 더 이상 참조하지 않겠다는 의미
함수가 유효한 값을 반환할 수 없는 경우 명시적으로 null을 반환하기도
ex) HTML 요소를 검색해 반환하는 document.querySelector 메서드는 조건에 부합하는 HTML 요소를 검색할 수 없는 경우 에러 대신 null을 반환
심벌 타입
심벌은 ES6에서 추가된 7번째 타입으로, 변경 불가능한 원시 타입의 값
→ 심벌 값은 다른 값과 중복되지 않는 유일무이한 값
→ 주로 이름이 충돌할 위험이 없는 객체의 유일한 프로퍼티 키를 만들기 위해 사용
심벌은 Symbol 함수를 호출해 생성.
→ 이때 생성된 심벌 값은 외부에 노출 x, 다른 값과 절대 중복되지 않는 유일무이한 값
// 심벌 값 생성
var key = Symbol('key');
console.log(typeof key); // symbol
// 객체 생성
var obj = {};
// 이름이 충돌할 위험이 없는 유일무이한 값인 심벌을 프로퍼티 키로 사용
obj[key] = 'value';
console.log(obj[key]); // value
객체 타입
자바스크립트는 객체 기반의 언어이며, 자바스크립트를 이루고 있는 거의 모든 것이 객체
→ 지금까지 살펴본 6가지 데이터 타입 이외의 값은 모두 객체 타입
데이터 타입의 필요성
데이터 타입에 의한 메모리 공간의 확보와 참조
자바스크립트 엔진은 데이터 타입, 즉 값의 종류에 따라 정해진 크기의 메모리 공간을 확보한다.
→ 변수에 할당되는 값의 데이터 타입에 따라 확보해야할 메모리 공간의 크기가 결정
심벌 테이블
컴파일러 또는 인터프리터는 심벌 테이블이라고 부르는 자료 구조를 통해 식별자를 키로 바인딩된 값의 메모리 주소, 데이터 타입, 스코프 등을 관리
데이터 타입이 필요한 이유를 정리하자면,
- 값을 저장할 때 확보해야 하는 메모리 공간의 크기를 결정하기 위해
- 값을 참조할 때 한 번에 읽어 들여야 할 메모리 공간의 크기를 결정하기 위해
- 메모리에서 읽어 들인 2진수를 어떻게 해석할지 결정하기 위해
ex) 0010 0001을 숫자로 해석하면 65지만 문자열로 해석하면 ‘A’다.
동적 타이핑
C와 자바 같은 정적 타입(static/strong type) 언어는 변수를 선언할 때 변수에 할당할 수 있는 값의 종류인 데이터 타입을 사전에 선언해야 한다. → 명시적 타입 선언(char이나 int 같은)
정적 타입 언는 변수의 타입을 변경할 수 없으며, 변수에 선언한 타입에 맞는 값만 할당 가능(C, C++, 자바, 코틀린, 고, 하스켈, 러스트 등..)
자바스크립트는 정적 타입 언어와 다르게 변수를 선언할 때 타입을 선언하지 않는다.
→ 어떠한 데이터 타입의 값이라도 자유롭게 할당 가능
자바스크립트의 변수는 선언이 아닌 할당에 의해 타입이 결정(타입 추론, type inference)
재할당에 의해 변수의 타입은 언제든지 변할 수 있음
→ 동적 타이핑
→ 자바스크립트는 동적 타입(dynamic/weak type) 언어
동적 타입 언어는 유연성은 높지만 신뢰성은 떨어진다.
변수를 사용할 때 주의할 사항
- 변수는 꼭 필요한 경우에 한해 제한적으로 사용
- 변수의 유효 범위(스코프)는 최대한 좁게 만들어 변수의 부작용을 억제해야
- 전역 변수는 최대한 사용하지 않도록
- 변수보다는 상수를 사용해 값의 변경을 억제
- 변수 이름은 변수 목적이나 의미를 파악할 수 있도록 네이밍
결론: 가독성이 좋은 코드가 좋은 코드
7장 - 연산자
연산자는 하나 이상의 표현식을 대상으로 산술, 할당, 비교, 논리, 타입, 지수 연산 등을 수행해 하나의 값을 만듦
피연산자: 연산의 대상
산술 연산자
산술 연산자는 피연산자를 대상으로 수학적 계산을 수행해 새로운 숫자 값을 만듦
→ 산술 연산이 불가능한 경우, NaN을 반환
이항 산술 연산자
2개의 피연산자를 산술 연산하여 숫자 값을 만듦
모든 이항 산술 연산자는 피연산자의 값을 변경하는 부수 효과가 없다.
→ 덧셈, 뺄셈, 곱셈, 나눗셈, 나머지
단항 산술 연산자
단항 산술 연산자는 1개의 피연산자를 산술 연산하여 숫자 값을 만듦
++ → 증가
-- → 감소
- → 효과 x
- → 양수를 음수로, 음수를 양수로 반전한 값을 반환
증가/감소 연산자는 피연산자의 값을 변경하는 부수효과가 있다.
피연산자 앞에 위치한 전위 증가/감소 연산자
- 먼저 피연산자의 값을 증가/감소
- 그리고 다른 연산을 수행
피연산자 뒤에 위치한 후위 증가/감소 연산
- 먼저 다른 연산을 수행한 후
- 피연산자의 값을 증가/감소
숫자 타입이 아닌 피연산자에 + 단항 연산자를 사용하면 피연산자를 숫자 타입으로 변환하여 반환
- 불리언 값 앞에 붙이면 숫자로 타입 변환(true는 1, false는 0으로)
- 문자열에 +를 붙이면 문자열은 숫자로 타입을 변환할 수 없으므로 NaN을 반환
-’10’은? -10이다.
-true는? -1이다.
-’Hello’는? NaN이다.
문자열 연결 연산자
- 연산자는 피연산자 중 하나 이상이 문자열일 경우 문자열 연결 연산자로 동작
'1' + 2 // '12'
1 + '2' // '12'
1 + true; // 2
1 + false; // 1
1 + null; // 1
+undefined; // NaN
1 + undefined; // NaN
1 + true를 연산하면 자바스크립트 엔진은 암묵적으로 불리언 타입의 값인 true를 숫자 타입인 1로 타입을 강제로 변환한 후 연산을 수행
→ 암묵적 타입 변환(implicit coercion) 또는 타입 강제 변환(type coercion)
할당 연산자
할당 연산자는 우항에 있는 피연산자의 평가 결과를 좌항에 있는 변수에 할당(부수효과 o)
var x;
x = 10;
console.log(x); // 10
x += 5; // x = x + 5;
console.log(x); // 15
x -= 5; // x = x - 5;
console.log(x); // 10
x *= 5; // x = x * 5;
console.log(x); // 50
x /= 5; // x = x / 5;
console.log(x); // 10
x %= 5; // x = x % 5;
console.log(x); // 0;
var str = 'My name is ';
// 문자열 연결 연산자
str += 'Lee'; str = str + 'Lee';
console.log(str); // 'My name is Lee'
할당문은 값으로 평가되는 표현식인 문으로서 할당된 값으로 평가된다.
→ 여러 변수에 동일한 값을 연쇄 할당 할 수 있다.
var a, b, c;
a = b = c = 0;
console.log(a, b, c); // 0 0 0
비교 연산자
비교 연산자는 좌항과 우항의 피연산자를 비교 다음 그 결과를 불리언 값으로 반환
동등/일치 비교 연산자
동등 비교(==) 연산자는 좌항과 우항의 피연산자를 비교할 때 먼저 암묵적 타입 변환을 통해 타입을 일치 시킨 후 같은 값인지 비교한다.
5 == ‘5’; // → true
동등 비교 연산자는 사용하지 않는 편이 좋고, 대신 일치 비교(===) 연산자를 사용한다.
일치 비교(===) 연산자는 좌항과 우항의 피연산자가 타입도 같고 값도 같은 경우에 한하여 true를 반환
→ 암묵적 타입 변환을 하지 않고 값을 비교
// NaN은 자신과 일치하지 않는 유일한 값
NaN === NaN // -> false
숫자가 NaN인지 조사하려면 빌트인 함수 Numberr.isNaN을 사용한다.
자바스크립트는 양의 0과 음의 0이 있는데 이들을 비교하면 true를 반환한다.
→ Object.is 메서드를 활용하면 -0과 0 / NaN 간의 정확한 비교 결과를 반환
대소 관계 비교 연산자
> , <. >=, <= 사용
삼항 조건 연산자
조건식 ? 조건식이 true일 때 반환할 값 : 조건식이 false일 때 반환할 값
var x = 2;
var result = x % 2 ? '홀수 : '짝수';
console.log(result); // 짝수
삼항 조건 연산자 표현식은 값처럼 사용할 수 있지만 if…else문은 값처럼 사용할 수 없다.
→ 삼항 조건 연산자 표현식은 값으로 평가할 수 있는 표현식인 문
→ 조건에 따라 어떤 값을 결정해야 한다면 if…else 문보다 삼항 조건 연산자 표현식을 사용하는 편이 유리
논리 연산자
논리 연산자는 우항과 좌항의 피연산자(부정 논리 연산자는 우항의 피연산자)를 논리 연산
|| → 논리합(OR)
&& → 논리곱(AND)
! → 부정(NOT)
드 모르간의 법칙을 활용해 복잡한 표현식을 좀 더 가독성 좋게 변환할 수 있다.
쉼표 연산자
쉼표 연산자는 왼쪽 피연산자부터 차례대로 피연산자를 평가하고 마지막 피연산자의 평가가 끝나면 마지막 피연산자의 평가 결과를 반환
그룹 연산자
소괄호(’()’)로 피연산자를 감싸는 그룹 연산자는 자신의 피연산자인 표현식을 가장 먼저 평가
→ 그룹 연산자는 연산자 우선순위가 가장 높다
typeof 연산자
type 연산자는 7가지 문자열 “string”, “number”, “boolean”, “undefined, “symbol”, “object”, “function” 중 하나를 반환. 함수는 “function”을 반환
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
주의: typeof 연산자로 null 값을 연산해보면 null이 아닌 object를 반환
→ 값이 null 타입인지 확인할 때는 일치 연산자(===)를 사용하자
주의: 선언하지 않은 식별자를 typeof 연산자로 연산하면 ReferenceError가 발생하지 않고 undefined를 반환
지수 연산자
ES7에서 도입된 지수 연산자는 좌항의 피연산자를 밑으로, 우항의 피연산자를 지수로 거듭 제곱하여 숫자 값을 반환
2 ** 2 = 4
2 ** -2 = 0.25
지수 연산자가 도입되기 이전에는 Math.pow 메서드를 사용
음수를 거듭제곱의 밑으로 사용해 계산하려면 괄호로 묶어야한다.
-5 ** 2 X
(-5) ** 2 O
- 지수 연산자는 할당 연산자와 함께 사용 가능
- 지수 연산자는 이항 연산자 중 우선순위가 가장 높음
그 외의 연산자
?. → 옵셔널 체이닝 연산자
?? → null 병합 연산자
delete → 프로퍼티 삭제
new → 생성자 함수를 호출할 때 사용하여 인스턴스 생성
instanceof → 좌변의 객체가 우변의 생성자 함수와 연결된 인스턴스인지 판별
in → 프로퍼티 존재 확인
delete 연산자는 객체의 프로퍼티를 삭제하는 부수 효과가 있다.
연산자 우선순위, 연산자 결합 순서
기억에 의존하기엔 너무 많다..
8장 - 제어문
제어문은 조건에 따라 코드 블록을 실행(조건문)하거나 반복 실행(반복문)할 때 사용한다.
제어문은 코드의 흐름을 이해하기 어렵게 만들어 가독성을 해치는 단점이 있다.
블록문
블록문은 0개 이상의 문을 중괄호로 묶은 것으로, 코드 블록 또는 블록이라고 부르기도 한다.
→ 자바스크립트는 블록문을 하나의 실행 단위로 취급
→ 블록문의 끝에는 세미콜론을 붙이지 않음
조건문
조건문은 주어진 조건식의 평가 결과에 따라 코드 블록(블록문)의 실행을 결정한다.
→ 조건식은 불리언 값으로 평가될 수 있는 표현식
조건문에는 if…else문과 switch문이 있다.
삼항 연산자에서 경우의 수가 세가지라면?
var num = 2;
// 0은 false로 취급된다
var kind = num ? (num > 0 ? '양수' : '음수' ) : '영';
console.log(kind); // 양수
반복문
반복문은 조건식의 평가 결과가 참일 경우 코드 블록을 실행
자바스크립트는 세 가지 반복문인 for문, while문, do…while 문을 제공
→ 배열을 순회할 때 사용되는 forEach 메서드, 객체의 프로퍼티를 열거할 때 사용하는 for…in문, ES6에서 도입된 이터러블을 순회할 수 있는 for … of 문과 같이 반복문을 대체할 수 있는 다양한 기능을 제공
for문
for (변수 선언문 또는 할당문; 조건식; 증감식) {
조건식이 참인 경우 반복 실행될 문;
}
for문의 변수 선언문, 조건식, 증감식은 모두 옵션이므로 반드시 사용할 필요는 없다.
단, 어떤 식도 선언하지 않으면 무한 루프가 된다.
while문
while문은 주어진 조건식의 평가 결과가 참이면 코드 블록을 계속해서 반복 실행
for문은 반복 횟수가 명확할 때 주로 사용하고 while문은 반복횟수가 불명확할때 주로 사용
do … while문
do…while문은 코드 블록을 먼저 실행하고 조건식을 평가
→ 코드 블록은 무조건 한 번 이상 실행
break문
break문은 코드 블록을 탈출
→ 정확히 말하자면 레이블문, 반복문 또는 switch문의 코드 블록을 탈출
레이블 문: 식별자가 붙은 문
→ 프로그램의 실행 순서를 제어하는 데 사용
(switch 문의 case 문과 default 문도 레이블 문)
// foo라는 식별자가 붙은 레이블 블록문
foo : {
console.log(1);
break foo; // foo 레이블 블록문을 탈출
console.log(2);
}
console.log('Done!');
중첩된 for 문에서 내부 for문이 아닌 외부 for 문을 탈출하려면 레이블 문을 사용
// outer라는 식별자가 붙은 레이블 for 문
outer: for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++ _ {
// i + j === 3이면 outer라는 식별자가 붙은 레이블 for문을 타룿ㄹ
if(i + j === 3) break outer;
console.log(`inner [${i}, ${j}]`);
}
}
레이블 문은 중첩된 for문 외부로 탈출할 때 유용하지만 그 밖의 경우에는 권장되지 않는다.
continue문
continue문은 반복문의 코드 블록 실행을 현 지점에서 중단하고 반복문의 증감식으로 실행 흐름을 이동 시킴. → break문처럼 반복문 탈출 x
'Modern JS Deep Dive' 카테고리의 다른 글
[JS Deep Dive] 12장 정리 -함수에 대하여 (2) | 2024.10.01 |
---|---|
[JS Deep Dive] 10장, 11장 정리 - 객체 리터럴 | 원시 값과 객체의 비교에 대하여 (2) | 2024.10.01 |
[JS Deep Dive] 9장 정리 - 타입 변환과 단축 평가에 대하여 (3) | 2024.10.01 |
[JS Deep Dive] 4,5장 정리 - 변수, 표현식과 문에 대하여 (2) | 2024.09.17 |
[JS Deep Dive] 1,2,3장 정리 - 프로그래밍과 자바스크립트에 대하여 (0) | 2024.09.16 |