모던 자바스크립트 Deep Dive 정리
원시 타입과 객체 타입
▶JS의 데이터 타입(7개)은 2가지로 나눌 수 있음
1. 원시 타입 (숫자, 문자열, 불리언, undefined, null, symbol)
2. 객체 타입 (객체, 함수, 배열)
▶원시 타입 (원시 값)
▷변경 불가능한 값 (읽기 전용)
▷변수에 할당하면 실제 값이 저장됨
▶객체 타입
▷변경 가능한 값
▷변수에 할당하면 참조값(메모리 주소)이 저장됨
원시 값
▶원시 값은 변경 불가능하다
▷예시
var str = 'string';
// 문자열은 유사 배열(+이터러블)이므로 배열과 유사하게 인덱스를 사용해 각 문자에 접근할 수 있다.
console.log(str[0]); // s
// 문자열은 원시값이므로 변경할 수 없다. 이때 에러가 발생하지 않는다.
str[0] = 'S';
console.log(str); // string
// 원시 값인 문자열이 객체처럼 동작한다.
console.log(str.length); // 6
console.log(str.toUpperCase()); // STRING
값에 의한 전달
▶원시 값은 복사되어 전달된다
▷예시
let score = 80;
// copy 변수에는 score 변수의 값 80이 복사되어 할당된다.
let copy = score;
console.log(score, copy); // 80 80
console.log(score === copy); // true
// score 변수와 copy 변수의 값은 다른 메모리 공간에 저장된 별개의 값이다.
// 따라서 score 변수의 값을 변경해도 copy 변수의 값에는 어떠한 영향도 주지 않는다.
score = 100;
console.log(score, copy); // 100 80
console.log(score === copy); // false
▶ 항상 기억할 것은 변수(식별자)는 메모리 주소를 기억하고 있다 (값 자체가 아닌)
객체
▶객체는 변경 가능한 값이다
▷예시
const person = {
name: 'Lee'
};
// 프로퍼티 값 갱신
person.name = 'Kim';
// 프로퍼티 동적 생성
person.address = 'Seoul';
console.log(person); // {name: "Kim", address: "Seoul"}
▶원시 값을 할당한 변수를 참조하면 메모리에 저장된 원시 값에 접근한다
▷예시
변수 | 메모리 주소 | 메모리 |
score | 0x00001234 | 80 (원시 값) |
▶객체를 할당한 변수를 참조하면 메모리에 저장된 참조값을 통해 실제 객체에 접근한다
▷예시
변수 | 메모리 주소 | 메모리 |
person | 0x00004567 | 0x00005678 (객체의 메모리 주소) |
0x00005678 | { name : 'Lee' } (객체) |
▶객체가 변경 가능한 값인 이유 (참조에 의한 전달을 사용하는 이유)
▷메모리를 효율적으로 사용하기 위함
▷변수처럼 복사하여 값을 전달하면, 객체는 어떤 값인지 정해지지 않았기 때문에 (배열.. 객체.. 함수 등) 메모리 비효율적
▷이러한 단점은 여러 개의 식별자가 하나의 객체를 공유하여 서로 영향을 주고받는다는 단점을 보인다
참조에 의한 전달
▶깊은 복사의 경우 두 객체 중 하나를 바꾸면 나머지 객체도 영향을 받는다
▷예시 (객체)
const obj = {
name: 'kim',
score: {
math: 80,
science: {
bio: 100,
chem: 90
}
}
};
// 참조값을 복사
const test = obj;
// obj와 test는 동일한 참조값을 갖는다.
console.log(obj === test); // true
console.log(test.score.science.chem); // 90
// test를 통해 객체를 변경한다
test.score.science.chem = 75;
// obj에 변경사항이 반영된다
console.log(obj.score.science.chem); // 75
▷예시 (배열)
const arr = [2, 4, 6, 8];
const test = arr;
arr.push(1);
arr[0] = 3;
// 객체와 마찬가지로 변경사항이 공유된다
console.log(arr); // [3, 4, 6, 8, 1]
console.log(test); // [3, 4, 6, 8, 1]
▶얕은 복사
▷예시 (배열)
const arr1 = [1, 2, 3];
const shallowCopy1 = [...arr1];
arr1[0] = 10;
// 얉은 복사의 경우 변경사항이 공유되지 않는다
console.log(arr1); // [10, 2, 3] // shallowCopy1 을 바꾸면 shallowCopy1 만 적용됨
console.log(shallowCopy1); // [1, 2, 3]
▷객체의 얉은 복사의 경우, 변경사항이 모두에게 적용된다 (배열과 다름)
▷예시
const obj = {
name: 'kim',
score: {
math: 80,
science: {
bio: 100,
chem: 90
}
}
};
// 얕은 복사
const test = { ...obj };
obj.score.science.bio = 'changed';
console.log(test === obj); // false
// 변경사항이 모두에게 적용
console.log(test.score.science.bio === obj.score.science.bio); // true