자바스크립트는 다른 프로그래밍 언어에 비해서 데이터 타입이 상대적으로 유연한 특징이 있다. 이는 데이터 타입이 상황에 따라 변할 수 있다는 의미이다.
데이터 타입은 총 8가지가 있다.
| 기본형 (Primitive Type) | 참조형 (Reference Type) |
|---|---|
| Number String Boolean Null Undefined | Object |
| (ES2015) Symbol (ES2016) BigInt |
Symbol: 다른 값과 중복되지 않는 유일한 값을 만들어 낼 때 사용하는 타입
Bigint: 엄청 큰 수를 다룰 때 사용하는 타입
(두 가지는 많이 쓰이지 않는다.)
우리가 사용하는 값이 어떤 데이터 타입을 가지고 있는지 확인하려면 typeof 연산자를 사용해야 한다. 하지만 typeof 연산자의 결과가 모든 타입과 1:1로 매칭되지 않는다.
일단, typeof null은 null이 아닌 문자열 object가 리턴된다. 그리고 함수에 typeof 연산자를 사용하면 function이라는 값을 리턴한다. 자바스크립트에서 함수는 객체로 취급되어서 object를 리턴할거라 예상하지만, function이 리턴된다.
자바스크립트에서는 if, for, while문처럼 boolean 타입의 값이 필요한 맥락에서는 boolean이 아닌 다른 타입의 값들도 boolean 타입으로 평가되는 특징이 있다. 다시 말해 boolean이 아닌 타입의 값이 boolean 타입으로 형 변환 된다는 것이다.
| Falsy값 | Truthy값 |
|---|---|
| false null undefined NaN 0 '' | 나머지 값들 { } [ ] |
우리가 알고자 하는 값을 boolean() 함수를 통해서 직접 변환해 볼 수도 있다.
자바스크립트에서 논리 연산자는 매번 true 혹은 falseㄹ르 리턴하는 게 아니라 상황에 따라서 양쪽 값들 중 어느 한쪽을 선택하는 방식으로 동작한다.
AND 연산자는 양쪽 값이 모두 true인 경우에만 true를 리턴하고 어느 한쪽이라도 false일 경우 false를 리턴한다. 그런데 사실 자바스크립트에서 AND 연산자는 왼쪽 값이 truthy 하면 오른쪽 값을 리턴하고, 왼쪽 값이 falsy하면 그대로 왼쪽 값을 리턴하는 방식으로 동작한다.
OR 연산자는 양쪽이 모두 false일때만 false를 리턴하고 어느 한쪽이라도 true가 있을 때는 true가 리턴된다. OR 연산자도 둘 중 하나를 선택하는 관점에서 보면 AND 연산자와는 정반대로 왼쪽 값이 truthy 하면 그대로 왼쪽 값을 리턴하고 왼쪽 값이 falsy하면 오른쪽 값을 리턴한다는 걸 확인할 수 있다.
만약 AND 연산자나 OR 연산자를 섞어서 사용할 때는 연산의 우선순위가 존재한다. AND 와 OR 연산자 사이에서는 AND 연산자의 우선순위가 더 높다.
때문에 이를 명확하게 하기 위해서 여러 사람과 함께 협업하는 상황에서는 다양한 연산자들을 복합적으로 사용해야한다면 소괄호를 활용해서 의도에 맞는 연산 우선순위를 정확하게 표기하는 것이 좋은 습관이라는 점도 기억하는 것이 좋다.
물음표 두 개 (??)를 사용해서 null 혹은 undefined 값을 가려내는 연산자이다.
const example1 = null ?? 'I';
const example2 = undefined ?? 'love';
const example3 = 'Codeit' ?? 'JavaScript';
console.log(example1, example2, example3);
연산자 왼편의 값이 null이나 undefined라면 연산자 오른편의 값이 리턴되고, example3처럼 연산자 왼편의 값이 null이나 undefined가 아니라면 연산자 왼편의 값이 리턴되는 원리로 동작한다. 결과적으로 마지막 줄에서 콘솔에 출력되는 값은 I love Codeit이 된다.
null 병합 연산자가 OR 연산자와 동작하는 방식이 비슷해보이긴 하지만 null 병합 연산자 (??)는 왼편의 값이 null이나 undefined인지 확인하고 OR 연산자는 왼편의 값이 falsy인지를 확인하는 것이다.
변수는 이름을 통해서 어떤 값에 특별한 의미를 부여할 수 있는 하나의 상자라고 할 수 있다. 다르게 표현하면 프로그래밍에서 추상화의 가장 기본적인 수단이 바로 변수라고 할 수 있다.
ES2015 이전에는 var라는 키워드를 사용해서 변수를 만들었었는데, 이 키워드에는 몇 가지 문제가 있었다. 그래서 ES2015에서는 var키워드가 가진 문제를 해결하기 위해 let과 const라는 키워드가 등장했다. 최근에는 var보다는 활용 목적에 따라서 값의 재할당이 필요한 경우에는 let키워드를, 재할당이 필요하지 않은 경우에는 const 키워드를 통해서 변수를 만드는 방식이 좀 더 권장되고 있다.
var보다 let과 const를 사용해야 하는 이유에 대해서 알아보자.
1. 변수가 유효한 시점의 차이가 있다.
var 키워드는 변수를 만들기도 전에 사용이 가능한 문제가 있다.
console.log(title); // error가 아닌 undefined값이 출력된다.
var title;
이처럼 코드 상에서는 선언이 나중에 되었지만, 마치 이 선언이 위로 올라간 듯한 현상을 호이스팅(Hoisting)이라고 부른다. 호이스팅은 선언 부분만 끌어 올려지기 때문에 변수 선언과 동시에 값을 할당하더라도 할당된 값 자체는 그 이후에 접근이 가능하다는 점도 참고 해야한다.
console.log(age); // undefined
var age = 3;
console.log(age); // 3
*var 키워드는 선언 부분이 호이스팅 되는 특징 떄문에, 선언을 한 부분 이전에 사용을 할 수도 있다. 다만 선언과 동시에 값을 할당하면, 할당된 값은 선언 이후에 사용할 수 있다. 결과적으로 2번 줄에서 할당한 3은 2번 줄 이후부터 유효하고, 1번 줄에서는 선언 부분만 호이스팅 되어서 undefined 값이 출력된다.
let이나 const 키워드는 애초에 변수 선언 이전에 접근할 수가 없기 때문에 "선언 ㅣ전에 접근할 수 없다" 라는 에러 메시지가 나타난다. 때문에 예상치 못한 문제가 발생했을 때 그 원인을 파악하기가 훨씬 더 수월하다.
var title = 'Codeit';
console.log(title); // 'Codeit'
var title = 'JavaScript';
console.log(title); // 'JavaScript'
만약 이 두 선언 사이에 훨씬 더 많은 코드들이 있어서 실수로 이미 선언한 변수명을 중복으로 선언해 버리면 그 이후부터는 의도치 않게 위에서 선언한 코드잇이라는 값은 사라져버리게 된다.
반면에 let이나 const 키워드는 중복 선언이 불가능하기 때문에 한 번 선언했던 변수명을 나중에 또 선언하려고 하면 에러 메시지가 뜬다.
var x = 3; // Global Variable
function myFunc() {
var y = 4; // Local Variable
console.log(`x in myFunc: ${x}`);
console.log(`y in myFunc: ${y}`);
}
myFunc();
console.log(x);
console.log(y);
x는 전역 변수이기 때문에 함수 안에서나 함수 밖에서나 자유롭게 사용이 가능하고 y는 함수의 지역변수이니까 함수 밖에서는 사용할 수가 없다.
그러나 var 키워드는 함수 단위로만 구분이 되기 때문에 조건문이나 반목문 안에서 새로운 변수를 만들게 되더라도 모두 전역 변수로 평가된다. 어떤 조건문이나 반복문에서 고유하게 사용할 수 있는 지역변수는 만들 수가 없는 문제가 있던 것이다.
이 부분을 해결하기 위해서 let과 const 키워드는 중괄호가 사용되는 부분을 기준으로 변수의 유효 범위를 구분한다. 자바스크립트에서는 중괄호가 감싸진 부분을 "코드 블록"이라고 부른다.
let x = 3;
if (x < 4) {
let y = 3;
}
for (let i = 0; i < 5; i++) {
console.log(i);
}
console.log('x:', x);
console.log('y:', y);
console.log('i:', i);
if문 안에서 let 키워드로 선언된 변수 y는 if문의 코드 블록 안에 있는 지역 변수로 평가됐기 때문에 if문 밖에서는 사용할 수가 없다.
let과 const 키워드는 어떤 문법에 해당하는 특별한 키워드 없이 단순히 코드 블록으로만 구분되어 있어도 모두 스코프를 구분하기 때문에 코드블록 밖에서는 에러가 나타난다.
var 키워드는 함수를 기준으로만 스코프가 결정되기 때문에 "함수 스코프" 를 가지고, let과 const 키워드는 코드 블록을 기준으로 스코프가 결정되기 떄문에 "블록 스코프"를 가진다라고 표현하기도 한다.