
1. 6장 - 데이터 타입
자바스크립트의 데이터 타입의 종류 - 원시타입 vs 객체 타입
원시 타입
- Number : 숫자 정수 실수 구분 없이 하나의 숫자 타입 | Infinity, -Infinity, NaN..
- String : 문자열 타입
- Bollean : 논리적 참(true)과 거짓(false)
- undefined 타입 : var 키워드로 선언된 변수에 암묵적으로 할당되는 값
- null 타입 : 값이 없다는 것을 의도적으로 명시할 때 사용하는 값
- symbol 타입 : 변경 불가능한 원시 타입의 값이며 다른 값과 중복되지 않는 유일 무이한 값
객체
- 객체, 함수, 배열
==> JS는 객체 기반의 언어이며, 자바스크립트를 이루고 있는 거의 모든 것이 객체
숫자 타입
자바스크립트는 하나의 숫자 타입만 존재하며 다른 언어의 int, long, float 등을 구분하지 않는다.
--> 모든 수를 실수로 처리하며 모두 10진수로 해석
--> NaN의 경우 대소문자를 구분하여 써주어야 하며 다르게 사용하였을 시, ReferenceError가 발생한다.
문자열 타입
문자열은 JS에서 원시타입으로 변경 불가능한 값 (문자열 생성 시 문자열 변경 X)
- ' '(작은따옴표)
- " "(큰 따옴표)
- ` `(백틱)
키워드나 식별자 같은 토큰과 구분하기 위해 위 3가지로 묶어서 사용한다.
0개 이상의 16비트 유니코드 문자(UTF-16)의 집합으로 전 세계 대부분의 문자를 표현
템플릿 리터럴
ES6부터 도입된 문법이며 런타임에 일반 문자열로 변환되어 처리되며, 멀티라인 문자열, 표현식 삽입을 할 때 유용하게 사용된다.
표현식의 경우 ${variable} 형식으로 백 틱 안에 있는 문자열 안에 변수를 넣어 주면 간단히 문자열에 넣어서 사용할 수 있다.
undefined 타입
var 키워드로 선언한 변수는 암묵적으로 undefined로 초기화된다.
--> 개발자가 의도적으로 할당하는 값이 아닌 자바스크립트 엔진이 변수를 초기화할 때 사용하는 값
--> 변수를 참조했을 때 undefined가 반환된다면, 초기화되지 않은 변수라는 것을 간파할 수 있다.
(변수에 값이 없다는 것을 알리고 싶을 때는 null을 사용한다.)
선언과 정의
다른 언어에선 선언은 식별자의 존재를 알리는 것, 정의는 메모리 주소를 할당하는 것인데 자바스크립트는 변수를 선언하면 암묵적으로 정의가 이루어짐(undefined가 할당)
ECMASCript 사양에서 변수는 '선언한다'라고 표현하고 함수는 '정의한다'라고 표현.
null 타입
변수에 값이 없다는 것을 알리고 싶을 때 의도적으로 명시할 수 있다.
변수에 null을 할당하면, 변수가 이전에 참조하던 값을 더 이상 참조하지 않겠다는 의미
이 null을 할당하는 것은 더 이상 변수가 참조하던 값을 참조하지 않고, 참조를 제거하며, 메모리 공간에 가비지 컬렉션을 수행하게 됨.
HTML의 경우, querySelector 사용 시, 조건에 부합하는 요소가 없다면 null을 반환한다.
심벌 타입
ES6에서 추가된 7번째 타입으로, 변경 불가능한 원시 타입의 값이며 다른 값과 중복되지 않는 유일 무이한 값.
주로 이름이 충돌할 위험이 없는 객체의 유일한 프로퍼티 키를 만들기 위해 사용
Symbol('값') -> 이렇게 사용 가능
객체 타입
위에서 언급한 타입을 제외한 나머지는 모두 객체 타입이다.
JS는 객체 기반의 언어이며, 자바스크립트를 이루고 있는 거의 모든 것이 객체
데이터 타입의 필요성
- 값 저장 시, 확보해야 하는 메모리 공간의 크기 결정
- 값 참조 시, 읽어 들어야 하는 메모리 공간 크기 결정
- 메모리에서 읽은 값을 어떻게 해석할지 결정
데이터 타입에 의한 메모리 공간의 확보와 참조
데이터 타입에 따라 메모리 공간을 얼마나 잡고 읽어 들어야 할지 확인하기 위해 (메모리 공간의 크기)
모든 값은 데이터 타입을 가지며, 메모리에 2진수 즉, 비트의 나열로 저장
(메모리에 2진수의 01000001을 숫자로 해석하면 65, 문자열로 해석하면 'A'
심벌 테이블
컴파일러 또는 인터프리터는 심벌 테이블이라고 부르는 자료 구조를 통해 식별자를 키로 바인딩된 값의 메모리 주소, 데이터 타입, 스코프 등을 관리한다.
동적 타이핑
동적 타입 언어와 정적 타입 언어
정적타입: 데이터의 타입을 사전에 정의(int, char 등의 키워드 이용)
동적타입: 타입을 사전에 정의하지 않음(JS의 경우, var, let, const 키워드 이용)
* 자바스크립트는 동적타이핑으로 변수의 선언이 아닌 할당에 의해 타입이 결정(타입 추론) 된다. 또한 재할당에 의해 변수의 타입은 언제든지 동적으로 변할 수 있다.
* 유연성은 높지만 신뢰성은 떨어진다.
동적 타입 언어와 변수
동적 타입 언어의 구조적 단점은 변화하는 변수 값을 추적하기 어렵고, 값을 확인하기 전에는 타입을 확신할 수 없다. 이로 인해 유연성은 높지만 신뢰성이 떨어진다.
따라서 변수 사용 시 유의사항이 존재한다.
- 변수는 꼭 필요한 경우에 한해 사용
- 변수의 유효범위를 최대한 좁게 하여 변수 부작용을 억제
- 전역변수는 최대한 사용 X
- 변수보다는 상수를 사용
- 변수 이름은 변수의 목적이나 의미를 파악할 수 있도록 네이밍 하자.
코드는 오해하지 않도록 작성해야 하고, 가독성이 좋은 코드가 좋은 코드이다.
"컴퓨터가 이해하는 코드는 어떤 바보도 쓸 수 있다. 하지만 훌륭한 프로그래머는 사람이 이해할 수 있는 코드를 쓴다." - 마틴 파울러
2. 7장 - 연산자
연산자의 종류 : 산술, 할당, 비교, 논리, 타입 지수 연산
연산의 대상: 피연산자(값으로 표현될 수 있는 표현식)
연산자: 피연산자를 연산하여 새로운 값을 만드는 역할
산술 연산자
피연사를 대상으로 수학적 계산을 수행해 새로운 숫자값을 만든다.
산술 연산자로 새로운 숫자 값을 만들며 불가능한 경우 NaN을 반환한다.
이항 산술 연산자
2개의 피연산자를 사용하며 부수효과가 없다.
피연산자의 값이 바뀌지 않고 언제나 새로운 값을 만듦
종류: +, -, *, /, %
단항 산술 연산자
1개의 피연산자 사용
-> ++, -- : 피연산자를 증가시키거나 감소시키며 부수효과가 있음
-> +, - : 어떠한 효과도 없지만 -의 경우 양수를 음수로, 음수를 양수로 반전한 값 반환한다.
문자열 연결 연산자
+ 연산자는 피연산자 중 하나 이상이 문자열인 경우 문자열 연결 연산자로 동작
'1' + 2 // '12'
1 + '2' // '12'
1 + true // 2
1 + false // 1
1 + null // 1
+undefined // -> NaN
1 + undefined // -> NaN
JS 엔진은 암묵적으로 불리언 타입의 값인 true를 숫자 타입인 1로 타입을 강제로 변환 후 연산을 수행 (암묵적 타입변환, 타입 강제 변환)
할당 연산자
할당 연산자는 좌항에 변수 값을 할당하기 때문에 변수 값이 변하는 부수효과가 있다.
할당문은 표현식인 문으로, 할당된 값으로 평가된다.
비교 연산자
동등/일치 비교 연산자
동등 비교(==)의 경우 피연사자 비교 시 먼저 암묵적 타입 변환을 통해 타입을 일치시킨 후 같은 값인지 비교.
일치 비교(===)의 경우 피연산자 비교 시 타입도 같고 값도 같은 경우에 한하여 true를 반환
예외: NaN (NaN은 자신과 일치하지 않는 유일한 값)
Object.is
Object.is() 정적 메서드는 두 값이 같은 값이지 결정
동일, 일치 비교 연산자와 달리 0과 NaN결과가 다르며 예측 가능한 정확한 비교 결과를 반환한다. 그 외에는 일치 비교 (===) 연산자와 동일하게 동작한다.
-0 === +0; // true
Object.is(-0, +0); // false
NaN === NaN; // false
Object.is(NaN, NaN); // true
대소 관계 비교 연산자
피연산자의 크기를 비교하여 불리언 값을 반환한다.
삼항 조건 연산자
var x = 2;
var result = x % 2? '홀수' : '짝수';
console.log(result); // 짝수
첫 번째 피연산자가 true로 평가되면 두 번째 피연산자 반환, false이면 세 번째 피연산자를 반환한다.
삼항 조건 연산자 표현식은 값으로 평가할 수 있는 표현식인 문이다. 이 말은 즉, 값처럼 다른 표현식의 일부가 될 수 있어 유용하게 쓰일 수 있다. 가독성을 위해 조건에 따라 수행해야 할 문이 여러 개라면, if... else를 사용하는 것이 좋다.
드 모르간의 법칙
논리 연산자로 구성된 복잡한 표현식은 가독성이 좋지 않아 한눈에 이해하기 어려울 때가 있다. 이러한 경우 드 모르간의 법칙을 활용하면 복잡한 표현식을 좀 더 가독성 좋은 표현식으로 변환할 수 있다.
!(x || y) === (! x &&! y)
!(x && y) === (! x ||! y)
논리 연산자
종류: ||(논리합), &&(논리곱),!(부정)
부수효과가 없으며, 피 연산자가 불리언 타입일 필요는 없고 불리언 타입으로 암묵적으로 변환되어 연산됨
쉼표 연산자
var a, b, c;
a = 1, b = 2, c = 3; // 콘솔에서 3을 반환한다.
그룹 연산자
()을 의미하며 연산자 우선순위가 가장 높다.
3 * (4 + 1); // 15
typeof 연산자
typeof은 피연산자의 데이터 타입을 문자열로 반환한다.
string, number, boolean, undefined, symbol, object, function 중 하나 반환. null을 반환하는 경우 없음
값이 null타입인지 확인하고 싶을 때는 일치연산자(===)를 사용하여 확인.
선언하지 않은 식별자를 typeof으로 연산 시, ReferenceError가 발생하지 않고 undefined를 반환.
// notVariable 선언한 적 X
typeof notVariable; // undefined
지수 연산자
**으로 사용하며, 지수 연산자 전에는 Math.pow를 사용하였다.
음수 제곱 시 (-5) ** 2 = 25와 같이 괄호로 묶어야 한다.
다른 산술 연산과 마찬가지로 할당문과 같이 사용할 수 있으며(num **= 2) 다른 이항 연사자들보다 우선순위가 높다.
그 외의 연산자
연산자 | 개요 |
?. | 옵셔널 체이닝 연산자 |
?? | null 병합 연산자 |
delete | 프로퍼티 삭제 |
new | 생성자 함수를 호출할 때 사용하여 인스턴스 생성 |
instanceof | 좌변의 객체가 우변의 생성자 함수와 연결된 인스턴스인지 판별 |
in | 프로퍼티 존재 확인 |
연산자의 부수 효과
다른 코드에 영향을 주는 부수효과가 있는 연산자: 할당 연산(=), 증가/감소 연산(++/--), delete 연산자.
할당과 증감 및 감소 연산자는 변수 값을 바꾸며, delete의 경우 객체의 프로퍼티를 삭제한다.
연산자 우선순위
우선순위가 가장 높은 것은 ()이며 그 외에는 기억하기 어려우니 ()를 사용하여 명시적으로 우선순위를 조절하는 것을 권장
연산자 결합 순서
연산자의 어느 쪽(좌항 또는 우항)부터 평가를 수행할 것인지 나타내는 순서
좌항 -> 우항 : +, -, /, %, <, <=, >, >=, &&...
우항 -> 좌항 : ++, --, 할당 연산자(=, +=, -=,...),! x...
3. 8장 - 제어문
제어문은 조건에 따라 블록을 실행하거나 반복 실행하지만 이는 위에서 아래로 순차적으로 진행하는 코드의 흐름을 혼란스럽게 하여 가독성을 해친다. 보통 forEach, map, filter, reduce 같은 고차함수를 이용하여 해결
블록문
0개 이상의 문을 {} 중괄호로 묶은 것으로, 블록문이라 하며 블록문으 끝에는 자체 종결성을 갖기 때문에 ;세미콜론을 붙이지 않는다.
자바스크립트에서는 블록문을 하나의 실행단위로 취급한다.
조건문
JS는 if... else와 switch의 두 가지 조건문을 제공한다.
if... else
if... else문의 else if의 경우 여러 번 사용 가능하다. 만약 코드 블록 내의 문이 하나라면 중괄호 생략이 가능하다.
대부분의 if... else문은 삼항 조건 연산자로 바꿔 쓸 수 있고, 이 삼항 조건 연산자는 값처럼 사용할 수 있어서 유용하지만 조건에 따른 실행내용이 많을 경우, 가독성을 위해 if... else문을 사용하는 것이 좋다.
switch 문
if...else 문의 조건식은 불리언 값으로 평가되어야 하지만 switch 문은 불리언 값 보다 '문자열' 혹은 '숫자'인 값인 경우가 많다.
switch (표현식) {
case 표현식 1:
console.log(표현식1);
break;
case 표현식 2:
console.log(표현식2);
break;
default:
console.log(마지막);
}
위와 같이 사용하며 만약 break가 없이 문이 끝날 때까지 모든 케이스를 실행한다면 이를 폴스로 라고 한다. default 에는 일반적으로 break를 생략한다.
조건이 엄청 많은 경우 if... else문 보다 switch 문을 사용했을 대, 가독성이 더 좋다면 switch 문을 사용하는 것이 좋다.
반복문
총 for, while, do... while 문이 존재한다.
for
for는 처음 부분에 변수 선언 또는 할당문, 조건식, 증감식이 존재한다.
for (;;) {... } 은 무한루프를 발생시킨다.
while
for 문은 반복 횟수가 명확할 때, while문은 반복 횟수가 불명확할 때 주로 사용!
do... while 문
코드 블록을 무조건 한 번 이상 실행 시킨다.
var count = 0;
do {
console.log(count); // 0 1 2
count++;
} while (count < 3);
break 문
레이블 혹은 반복문을 탈출하는데 쓰인다.
레이블, 반복문, switch 문의 코드 블록 외에 break를 사용 시 SyntaxError가 발생한다.
레이블 문이란 식별자가 붙은 문으로 아래의 예시를 참고
// foo라는 식별자가 붙은 레이블 블록
foo: {
console.log(1);
break foo; // foo 레이블 블록문을 탈출한다.
console.log(2);
}
console.log('Done!');
레이블 문을 사용하게 되면 외부로 탈출할 때 유용하지만, 흐름이 복잡해져서 가독성이 나빠지고 오류를 발생시킬 가능성이 높아지기 때문에 권장하진 않음
continue 문
반복문의 코드 블록 실행을 현 지점에서 중단하고 반복문의 증감식으로 실행 흐름을 이동시킨다.
4. 9장 - 타입 변환 단축 평가
타입 변환이란?
개발자가 의도적으로 값의 타입을 변환시키는 것을 명시적 타입 변환 또는 타입 캐스팅이라고 한다.
개발자가 의도 없이 표현식을 평가하는 도중 JS엔진에 의해 암묵적으로 타입이 자동변환 되는 것을 암묵적 타입 변환 또는 타입 강제 변환이라 한다.
이러한 타입 변환은 기존의 원시 값을 직접 변경하는 것이 아닌 새로운 원시 값을 생성하여 단 한 번 사용하고 버린다.
중요한 것은 코드가 어떻게 작동되는 것인지 예측하고 이해하면서 사용해야 한다는 것이다.
암묵적 타입 변환
자바스크립트 엔진이 표현식을 평가할 때, 개발자의 의도와 상관없이 코드의 문맥을 고려해 암묵적으로 데이터 타입을 강제 변환하는 것
문자열 타입으로 변환
+ 연산자는 피 연산자 중 하나 이상이 문자열 이면 문자열 연결 연산자로 동작한다.
리터럴의 표현식 삽입 또한 평가 결과를 문자열 타입으로 암묵적 타입 변환한다.
숫자 타입으로 변환
-, *, /와 같은 산술 연산자는 피 연산자 중, 숫자 타입이 아닌 피연산자를 숫자타입으로 암묵적 타입 변환한다.
이 경우, 숫자 타입으로 변환할 수 없는 경우 산술 연산 수행이 불가능하여 표현식의 평가 결과가 NaN이 된다.
비교 연산자 또한 값을 비교하여 불리언 값을 만들기 때문에 피 연산자를 숫자 타입으로 암묵적 타입 변환한다.
불리언 타입으로 변환
JS엔진은 불리언 타입이 아닌 값을 Truthy 값(참으로 평가되는 값) 또는 Falsy 값(거짓으로 평가되는 값)으로 구분하는데, Truthy는 true로, Falsy는 false로 암묵적 타입 변환된다.
대표적 Falsy 값
- false
- undefined
- null
- -0, 0
- NaN
- ''(빈 문자열)
명시적 타입 변환
문자열 타입으로 변환
- new 연산자 없이 String 생성자 사용(ex: String(1);)
- Object.prototype.toString(ex: (1). toString();)
- 문자열 연결 연산자를 이용하는 방법(ex: 1 + '';)
숫자 타입으로 변환
- new 연산자 없이 Number 생성자 함수 사용(ex: Number('0');)
- parseInt, parsefloat 함수 사용 --> 문자열만 숫자 타입으로 변환 가능(ex: parseInt('0');)
- + 단항 산술 연산자 이용(ex: +'0';)
- * 산술 연산자 이용(ex: true * 1;)
불리언 타입으로 변환
- new 연산자 없이 Boolean 생성자 함수 사용(ex: Boolean('x');)
- ! 부정 논리 연산자를 두 번 사용(ex:!!'x';)
단축 평가
논리합과 논리곱연산자는 논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 변환하는데 이를 단축 평가라고 한다.
논리 연산자를 사용한 단축 평가
단축 평가 표현식 | 평가 결과 |
true || anything | true |
false || anything | anything |
true && anything | anything |
false && anything | false |
단축평가가 유용하게 사용되는 상황
- 객체가 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티를 참조할 때 (var value = elem && elem.value)
- 함수 매개변수에 기본 값을 설정할 때(기본값을 설정해 두면 undefined로 발생할 수 있는 에러 방지가능)
옵셔널 체이닝 연산자
?.로 사용하며 좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 함.
var elem = null;
var value1 = elem?. value;
console.log(value1); // undefined
var value2 = elem && elem.value;
console.log(value2); // null
var str = '';
// 문자열 길이를 참조하는데 좌항 피연산자가 null 또는 undefined가 아니기 때문에 우항의 프로퍼티 참조
var length = str?. length;
console.log(length); // 0
null 병합 연산자
??로 사용하며 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다.
null 병합 연산자?? 는 변수에 기본값을 설정할 때 유용하다.
var helloNull = null?? 'default string';
console.log(helloNull); // "default string"
// 만약 Falsy값인 0이나 ''도 기본값으로 유효시, 예기치 않은 동작 발생 가능
var foo = '' || 'default string';
console.log(foo); // "default string"
// 좌항의 피연산자가 Falsy 값이라도 null 또는 undefined가 아니면 좌항 피연산자 반환
var foo2 = ''?? 'default string';
console.log(foo2); // ""
끝
'WEB > 모던 자바스크립트 Deep Dive' 카테고리의 다른 글
[모던 자바스크립트 Deep Dive] 16 ~ 18장 (0) | 2024.07.01 |
---|---|
[모던 자바스크립트 Deep Dive] 13 ~ 15장 (0) | 2024.06.23 |
[모던 자바스크립트 Deep Dive] 10 ~ 12장 (1) | 2024.06.16 |
[모던 자바스크립트 Deep Dive] 1 ~ 5장 (1) | 2024.05.03 |