
자바스크립트의 모든 값은 데이터 타입(줄여서 '타입')을 갖고 크게 두 가지로 나눌 수 있다.
Number: 숫자 (정수, 실수)
String: 문자열
Boolean: true/false
Undefined: 정의되지 않은 값
Null: 값이 없다는 것을 의도적으로 명시할 때 사용하는 값
Symbol: ES6에서 추가된 고유한 식별자
BigInt: 큰 정수를 다루기 위한 타입
Object: 객체
Array: 배열
Function: 함수
Date, RegExp 등
숫자타입의 특별한 값
''), 큰 따옴표(""), 백틱(` ` )으로 텍스트를 감싼다.+를 사용해 연결할 수 있다.+연산자는 피연산자 중 하나 이상이 문자열인 경우 문자열 연결 연산자로 동작한다. 그 외의 경우는 덧셈 연산자로 동작한다.var first = 'kim';
var last = 'orange';
// ES5 문자열 연결
console.log('My name is ' + first + ' ' + last + '!');
console.log(`1 + 2 = ${1 + 2}); // 1 + 2 = 3
true, false뿐이다.// id는 새로운 심볼이 된다.
let id = Symbol();
심볼을 만들 때 심볼 이름이라 불리는 설명을 붙일 수도 있다. 심볼 이름은 디버깅 시 아주 유용하다.
let id = Symbol("id");
설명이 같은 심볼 2개를 만들고 비교 - 동일 연산자(==)로 비교시 false가 반환된다.
let id1 = Symbol("id");
let id2 = Symbol("id");
alert(id1 == id2); // false
자바스크립트에선 문자형으로의 암시적 형 변환이 자유롭게 일어나는편이다. alert함수가 거의 모든 값을 인자로 받을 수 있는 이유가 이 때문이다. 그러나 심볼은 예외이다.
심볼은 다른 자료형으로 암시적 형 변환(자동 형 변환)되지 않는다.
심볼을 이용하면 숨김(hidden) 프로퍼티(외부 코드에서 접근이 불가능하고 값도 덮어쓸 수 없는 프로퍼티)를 만들 수 있다.
{...}을 사용해 객체를 만든 경우, 대괄호를 사용해 심볼형 키를 만들어야 한다.let id = Symbol("id");
let user = {
name: "John",
[id]: 123 // "id": 123 은 안됨 -> "id": 123라고하면, 심볼 id가 아닌 문자열 id로 키가 된다.
}
Object.keys(obj) 에서도 키가 심볼인 프로퍼티는 배제된다.심볼형 프로퍼티 숨기기(hiding symbolic property)라 불리는 원칙 덕분에 외부 스크립트나 라이브러리는 심볼형 키를 가진 프로퍼티에 접근하지 못함Object.assing은 키가 심볼인 프로퍼티를 배제하지 않고 객체 내 모든 프로퍼티를 복사한다.전역 심볼 레지스트리(global symbol registry)를 이용하면 된다. Symbol.for(key)를 사용key인 심볼을 반환하고, 조건에 맞는 심볼이 레지스트리 안에 없으면 새로운 심볼 Symbol(key)를 만들고 레지스트리 안에 저장한다.Symbol.keyFor는 전역 심볼 레지스트리를 뒤져서 해당 심볼의 기름을 얻어낸다.Symbol.keyFor는 undefined를 반환var와 let은 초기화 과정에서 중요한 차이가 있다.
메모리 구조 예시
// 힙과 스택의 관계
let person = {
name: "John",
age: 30,
hobbies: ["reading", "music"]
};
스택 메모리 힙 메모리
------------------ ------------------------------
| | | |
| person: #123 | ----> | #123: |
| | | name: "John" |
------------------ | age: 30 |
| hobbies: #456 |
------------------------------
| #456: ["reading", "misuc"] |
------------------------------
// 1. Number() 생성자 함수
let num1 = Number("123"); // 명시적 변환
// 2. parseInt() / parseFload()
let num2 = parseInt("123"); // 정수로 변환
let num3 = parseInt("123.45"); // 부동소수점으로 변환
// 3. 단항 연산자 +
let num4 = +"123"; // 암시적 변환
// 4. Math.floor(), Math.ceil(), Math.round()
let num5 = Math.floor("123.45"); // 내림
let num6 = Math.ceil("123.45"); // 올림
let num7 = Math.round("123.45"); // 반올림
// 5. 비트 연산자 활용(|0, ~~)
let num8 = "123" | 0; // 비트 OR 연산
let num9 = ~~"123"; // 이중 NOT 비트 연산
Performance.now()를 사용하여 성능 비교
// 성능 테스트 함수
function performanceTest(fn, iterations = 1000000) {
const start = performance.now();
for (let i = 0; i < iterations; i++) {
fn();
}
return performance.now() - start;
}
// 다양한 방법 테스트
const testValue = "123.45";
const tests = {
'Number()': () => Number(testValue),
'parseInt()': () => parseInt(testValue),
'parseFloat()': () => parseFloat(testValue),
'unary operator +': () => +testValue,
'Math.floor()': () => Math.floor(testValue),
'Bitwise OR': () => testValue | 0,
'Double NOT': () => ~~testValue
};
// 각 방법의 성능 측정
Object.entries(tests).forEach(([name, fn]) => {
const time = performanceTest(fn);
console.log(`${name}: ${time.toFixed(2)}ms`);
});
연산 속도면에서 차이가 있다.
암시적 형변환은 코드를 간결하게 작성할 수 있는 장점이 있지만, 동시에 버그의 원인이 될 수 있다.
if(0 == '') 0과 빈 문자열이 암시적 형 변환을 통해 같다고 평가 된다.암시적 형 변환의 규칙을 이해하고, 필요한 경우 명시적 형 변환을 사용하여 코드의 명확성을 높이는 것이 중요하다.
- 암시적 형 변환이 예상치 못한 결과를 초래하고, 코드의 가독성을 저하시킬 수 있기 때문
: ES6에서 도입된 이터레이션 프로토콜은 순회 가능한(iterable) 데이터 컬렉션(자료구조)을 만들기 위해 ECMAScript 사양에 정의하여 미리 약속한 규칙