불 값은 참 true
또는 거짓 false
단 두 가지 값만 존재한다.
불 값은 일반적으로 비교 결과를 나타낸다.
a === 4
위 코드는 변수 a
의 값이 숫자 4와 일치하는지 검사한다.
비교 결과는 일치한다면 true
, 일치하지 않는다면 false
이다.
불 값은 제어문에서 자주 사용된다.
if (a === 4) {
b = b + 1;
} else {
a = a + 1;
}
위 코드는 a
가 4와 일치하는지 검사하고 일치한다면 b
에 1을 더하고 일치하지 않는다면 a
에 1을 더한다.
아래의 값은 모두 false
로 변환되며, 따라서 false
처럼 동작한다.
undefined
null
0
-0
NaN
"" // 빈 문자열
객체와 배열을 포함해 다른 값은 모두 true
로 변환되며 true
처럼 동작한다.
false
, 그리고 false
로 변환되는 위 여섯 가지 값을 묶어서 falsy
값이라고 부르고
나머지 값을 truthy
라고 부른다.
불 값에는 "true"나 "false" 문자열로 변환할 수 있는 toString()
메서드가 있지만 그 외의 유용한 메서드는 없다.
API는 단순한 편이지만 중요한 불 연산자가 세가지 있다.
&&
연산자는 불 AND 연산을 수행한다.truthy
값일 때만 true
로 평가되며 그 외의 경우는 모두 false
로 평가.||
연산자는 불 OR 연산을 수행한다.truthy
값은 값이면 true
로 평가되고, 두 피연산자가 모두 falsy
값이면 false
로 평가.!
단항 연산자는 불 NOT 연산을 수행한다.falsy
값이면 ture
로, 피연산자가 truthy
값이면 false
로 평가된다.null
은 값이 없음을 나타낼 때 사용하는 특별한 값이다.
null
에 typeof
연산자를 사용하면 문자열 "object"를 반환하는데, 이로 미뤄 null
은 '객체가 없다'는 것을 나타내는 특별한 객체 값이라 볼 수 있다.
하지만 현실에서 null
은 해당 타입의 유일한 멤버로 인식퇴며 객체뿐 아니라 숫자나 문자열에도 '값이 없다'는 의미로 사용될 수 있다.
undefined
값은 다른 의미에서 값이 없음을 나타낸다.
이 값은 초기화되지 않은 변수의 값이며 존재하지 않는 객체 프로퍼티나 배열 요소에 접근했을 때 반환되는 값이다.
또한 값을 명시적으로 반환하지 않는 함수의 반환 값이며, 전달되지 않은 인자의 값이기도 하다.
undefined
는 미리 정의된 전역 상수이며 그 값은 undefined
로 초기화 된다.
undefined
에 typeof
연산자를 적용하면 "undefined"를 반환한다.
즉, undefined
역시 특별한 타입이고 멤버는 그 하나뿐 이라는 뜻이다.
차이는 있지만 null
과 undefined
는 모두 값이 없다는 뜻이고 서로 바꿔 쓸 수 있을 때가 많다.
동등 연산자는 두 값이 동등하다고 간주하지만, 일치 연산자는 두 값을 구분한다.
두 값 모두 falsy
값이므로 불 값을 써야 하는 곳에서는 false
로 동작한다.
null
과 undefined
는 모두 프로퍼티나 메서드가 없다.
심벌(Symbol)은 문자열이 아닌 프로퍼티 이름으로 ES6에서 추가되었다.
심벌을 이해하기 위해서는 자바스크립트의 객체 타입이 프로퍼티의 순서 없는 집합이며 각 프로퍼티에 이름과 값이 있다는 것을 이해해야한다.
프로퍼티 이름은 일반적으로 문자열이지만 ES6 이후에는 심벌 역시 문자열과 같은 목적으로 사용할 수 있다.
let strname = "string name"; // 프로퍼티 이름에 문자열 사용
let symname = Symbol("propname"); // 프로퍼티 이름에 심벌 사용
typeof strname // "string"; strname은 문자열
typeof symname // "symbol"; symname은 심벌
let o = {}; // 새 객체 생성
o[strname] = 1; // 문자열 이름으로 프로퍼티 정의
o[symname] = 1; // 심벌 이름으로 프로퍼티 정의
o[strname] // 1; 문자열인 프로퍼티에 접근
o[symname] // 2; 심벌인 프로퍼티에 접근
심벌 타입에는 리터럴 문법이 없다.
심벌 값을 가져올 때는 Symbol()
함수를 호출한다. 이 함수는 절대 같은 값을 반환하지 않는다.
같은 인자로 호출하더라도 다른 값을 반환한다.
Symbol()
을 호출해 심벌 값을 얻었다면 객체의 기존 프로퍼티를 같은 이름으로 덮어 쓸 염려 없이 그 값을 프로퍼티 이름으로 추가할 수 있다는 뜻이다.
Symbol()
함수는 선택 사항인 인자로 문자열을 받고 고유한 심벌 값을 반환한다.
문자열 인자를 전달하면 그 문자열은 심벌의 toString()
메서드 결과에 포함된다.
하지만 같은 문자열을 전달해 Symbol()
을 다시 호출하더라도 그 결과는 완전히 다른 값이다.
이 객체의 프로퍼티는 전역으로 정의된 식별자이며 모든 자바스크립트 프로그램에서 사용할 수 있다.
자바스크립트 인터프리터를 시작할 때마다(또는 웹 브라우저가 새 페이지를 로드할 때마다) 아래와 같은 프로퍼티를 가진 새 전역 객체를 생성한다.
undefined
, Infinity
, NaN
같은 전역 상수isNaN()
, parseInt()
, eval()
같은 전역 함수Date()
, RegExp()
, String()
, Object()
, Arrat()
같은 생성자 함수Math
와 JSON
같은 전역 객체전역 객체의 초기 프로퍼티는 예약어가 아니지만 예약어로 간주해야 한다.
Node.js의 전역 객체에는 이름이 global
인 프로퍼티가 있으며 그 값은 전역 객체 자체이다.
따라서 Node.js 프로그램에서는 항상 global
이라는 이름으로 전역 객체를 참조할 수 있다.
웹 브라우저에서는 Window
객체가 모든 자바스크립트 코드의 전역 객체이다.
이 전역 Window
객체에는 자신을 참조하는 window
프로퍼티가 있으므로 이 프로퍼티를 통해 전역 객체를 참조할 수 있다. Window
객체에는 핵심 전역 프로퍼티가 정의되어 있고, 해당 웹 브라우저와 클라이언트 사이드 자바스크립트에 밀접한 전역 변수도 몇 가지 정의되어 있다.
ES2020에서 정의한 globalThis
는 어떤 환경에서든 전역 객체를 참조하는 표준이다.
자바스크립트에서 undefined
, null
, 불, 숫자, 문자열 같은 기본 값과 객체(배열, 함수) 사이에는 차이가 있다.
기본 값은 불변이며 기본 값을 "변경"하는 방법은 없다.
문자열은 문자의 배열이므로 특정 인덱스의 문자를 바꿀 수 있다고 생각할 수 있지만 자바스크립트는 이를 허용하지 않으며,
몇몇 메서드가 수정된 문자열을 반환하는 것처럼 보이지만 사실 새 문자열을 반환하는 것이다.
let s = "hello";
s.toUpperCase(); // "HELLO" 반환
s // "hello" 원래 문자열은 변경되지 않는다.
기본 값은 또한 값으로 비교한다. 두 값이 일치하려면 값이 같아야한다.
객체는 값으로 비교하지 않는다. 두 객체의 프로퍼티와 값이 같다고 해서 같은 객체가 아니라는 의미이다.
또한 두 배열에 같은 요소가 같은 순서로 존재한다해도 같은 배열이 아니다.
let o = {x : 1}, p = {x : 1}; // 프로퍼티가 같은 두 객체
o === p // false; 별개의 객체가 일치할 수 없다.
let a = [], b = []; // 빈 두 배열
a === b // false; 별개의 배열이 일치할 수 없다.
객체를 기본 타입과 구별하기 위해 참조 타입이라 부를 때도 있다.
이 용어는 객체 값은 참조이며, 객체는 참조로 비교한다는 뜻이다.
두 객체 값이 같다는 말은 오직 두 값이 같은 객체를 참조할 때만 성립한다.
let a = []; // 변수 a는 빈 배열을 가리킨다.
let b = a; // 변수 b는 변수 a와 같은 배열을 가리킨다.
b[0] = 1; // b가 참조하는 배열 변경
a[0] // 1; 변경된 부분은 변수 a를 통해서도 보인다.
a === b // true; a와 b는 같은 객체를 참조하므로 같은 값이다.
위 코드에서 볼 수 있듯 객체나 배열을 변수에 할당하는 것은 참조를 할당하는 것이다.
객체나 배열을 변수에 할당한다고 해서 객체의 사본이 새로 생기는 것은 아니다.
객체나 배열의 사본을 만들기 위해서는 반드시 객체 프로퍼티나 배열 요소를 직접 복사해야 한다.
별개의 객체나 배열을 비교할 때는 양쪽의 프로퍼티나 요소를 비교해야한다.
function equalArrays(a, b) {
if (a === b) return true; // 같은 배열 참조한다면 일치
if (a.length !== b.length) return false; // 크기다 다르면 불일치
for(let i = 0; i < a.length; i++) { // 요소 순회
if (a[i] !== b[i]) return false; // 어느 하나라도 다르면 불일치
}
return true; // 모두 같아면 일치
}