⛅ 원시타입 vs 객체타입
  | 변경 가능 유무 | 메모리 공간에 저장되는 값 | 변수 할당 방식 |
---|---|---|---|
원시 타입 | 변경 불가능 | 실제 값 저장 | 참조 값 저장 (값에 의한 전달) |
객체 타입 | 변경 가능 | 참조 값 저장 | 참조 값 복사 (참조에 의한 전달) |
⛅ 원시 값
- 변경 불가능한 값 === 한번 생성된 원시 값은 읽기 전용
- 원시 값 자체를 변경할 수 없다는 것이지 변수 값을 변경할 수 없다는 것이 아님!
- 원시 값을 할당한 변수에 새로운 원시 값을 재할당하면 메모리에 저장되어있던 원시값이 변경되는 것이 아닌 새로운 메모리 공간에 저장한 값을 가리키는 것 => 메모리 공간의 주소가 바뀌는 것임
- 변수가 참조하던 메모리 공간의 주소를 변경하는 것을 불변성 이라고 함
// 메모리 공간을 확보한뒤 kim이 저장되고,
// name이라는 식별자는 kim이 저장된 메모리 공간의 첫 번째 메모리 셀 주소를 가리킴
var name = 'kim';
// kim을 없애는 것이 아닌 donggyun을 새로운 메모리에 저장하고
// name 식별자는 donggyun 메모리의 주소를 가리키는 것 뿐임
name = 'donggyun';
// 유사 배열 객체 사용
console.log(name[0]); // d
// 원시 값인 문자열이 객체처럼 동작
console.log(name.length); // 8
console.log(name.toUpperCase); // DONGGYUN
// 문자열은 유사 배열이므로 객체가 아니라 원시 값임
// 불변성에 따라서 인덱스에 직접 값을 할당해도 변하지않음
name[0] = 'K';
console.log(name); // donggyun
❓유사 배열 객체란❓
- 배열처럼 인덱스 프로퍼티 값에 접근 가능
- length 프로퍼티를 갖는 객체
- for 문으로 순회 가능
🚨 원시 값을 객체처럼 사용하면 원시값을 감싸는 래퍼 객체로 자동 변환됨!
⛅️ 값에 의한 전달
// 우선 이 예제를 통해 값에 의한 전달을 이해해보자
var score = 80;
var copy = score;
console.log(score, copy); // 80 80
score = 100;
console.log(score); // 100
console.log(copy); // ?
- socre 변수와 copy 변수의 관계
- 1️⃣ score 변수는 0x01 메모리 주소를 갖고있음(80을 가진)
- 2️⃣ copy 변수에 score 변수의 0x01 메모리 주소(80을 가진)를 할당
- 3️⃣ score 변수에 100 할당 === 새로운 메모리주소 0x02(100을 가진)가 할당됨
- 4️⃣ score는 0x02(100) 주소를 가진 변수, copy는 0x01(80) 주소를 가진 변수
- 🚨 따라서 score 변수의 값이 바뀐다고해서 copy의 값이 바뀌는 것이 아니다!! 🚨
⛅️ 객체
- 프로퍼티 개수가 정해져 있지 않음
- 동적으로 프로퍼티 추가 가능
- 값에도 제약이 없음
- 변경 가능한 값임 === 이미 생성된 값에 접근하여 값 변경 가능
- 원시 값 처럼 크기가 일정하지도 않고, 프로퍼티 값이 객체일 수도 있기 때문에 생성하는 비용이 많이 듬 => 메모리의 효율적 소비가 어렵고 성능이 나쁘다.
- 따라서 객체는 변경 가능한 값으로 설계 되어있음(메모리 사용의 효율성과 성능을 위함)
- ( + 여러 개의 식별자가 하나의 객체를 공유 가능!! )
💡 자바스크립트 객체의 관리 방식
- 자바스크립트 객체 == 프로퍼티 키를 인덱스로 사용하는 해시 테이블(hash table)
- 클래스 없이 객체 생성 가능
- 동적으로 프로퍼티,메소드 추가 가능
- V8 엔진에서는 프로퍼티에 접근하기 위해 동적탐색 대신 히든 클래스 방식을 사용(프로퍼티 접근 성능 보장)
⛅️ 변경 가능한 값
- 객체를 할당한 변수가 기억하는 메모리 주소 공간에 접근하면 참조 값에 접근할 수 있음
- 참조값 === 생성된 객체가 저장된 메모리 공간의 주소
- 원시값을 할당한 변수를 참조 => 메모리에 저장되어 있는 원시 값에 접근
- 객체를 할당한 변수를 참조 => 메모리에 저장되어 있는 참조 값을 통해 실제 객체에 접근
- 객체를 할당한 변수는 재할당 없이 객체를 직접 변경 가능
- 재할당 하지 않았으므로 객체가 변경이 되었더라도 참조 값은 변경 X
var person = { name: 'donggyun' };
person.name = 'kim';
person.hobby = 'guitar';
console.log(person); // {name:'kim', hobby:'guitar'};
⛅️ 얕은 복사 vs 깊은 복사
- 얕은 복사: 객체를 한 단계까지만 복사 === 참조에 의한 전달
- 깊은 복사: 객체에 중첩되어 있는 객체까지 모두 복사(프로퍼티 값이 객체인것 까지 복사 함)
- 🚨 복사 했을때, 생성된 객체는 원본과 다른 객체이다 (참조 값이 다름!!) 🚨
const obj = { x: { y: 2 } };
// 스프레드 문법을 사용한 얕은 복사
const obj = { x: { y: 1, z: { say: 'hello' } } };
const copy = { ...obj };
copy.x.y = 100; // copy.x.y를 수정하면
console.log(obj.x.y); // 100 (원본 객체도 영향을 받음)
// lodash의 cloneDeep을 사용한 깊은 복사
const _ = require('lodash'); // lodash 라이브러리 사용
const obj = { x: { y: 1, z: { say: 'hello' } } };
const deepCopy = _.cloneDeep(obj);
deepCopy.x.z.say = 'hi';
console.log(obj.x.z.say); // 'hello' (원본 객체는 영향을 받지 않음)
// JSON을 사용한 깊은 복사
const obj = { x: { y: 1, z: { say: 'hello' } } };
const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.x.y = 100; // deepCopy.x.y를 수정해도
console.log(obj.x.y); // 1 (원본 객체는 영향을 받지 않음)
⛅️ 참조에 의한 전달
- 사실 자바스크립트에서 "값에 의한 전달" 과 "참조에 의한 전달"은 식별자가
기억하는 메모리 공간에 저장되어 있는 값을 복사해서 전달한다는 면에서 동일하다. - 따라서 자바스크립트는 "값에 의한 전달"만 존재한다.
- 즉 변수에 저장되어 있는 값이 원시 값이냐 참조 값이냐 의 차이!!
// 1️⃣ person 식별자에 정의된 리터럴 객체의 참조 값이 할당된다.
// 2️⃣ copy 객체에 person을 할당하는데 이때 person의 참조값을 복사해서 copy에 저장한다.
// 3️⃣ 결국 person과 copy가 동일한 참조 값을 가지게 된다.
// 4️⃣ 따라서 copy가 변경된다면 person 객체도 같이 변경이 된다.
var person = { name: 'donggyun' };
var copy = person;
- 객체의 비교
var person1 = { name: 'donggyun' };
var person2 = { name: 'donggyun' };
console.log(person1 === person2); // false => 두 객체는 생긴건 같지만 서로 다른 참조 값을 가지고있음(다른 객체임)
console.log(person1.name === person2.name); // true => 프로퍼티 name은 두 객체 모두 'donggyun' 이라는 원시 값으로 평가 되므로 같다
📚 REFERENCE
- 모던 자바스크립트 Deep Dive 11장 원시 값과 객체의 비교
'FE > Javascript' 카테고리의 다른 글
13. 모던 자바스크립트 Deep Dive(스코프) (1) | 2024.12.08 |
---|---|
12. 모던 자바스크립트 Deep Dive(함수) (1) | 2024.12.07 |
10. 모던 자바스크립트 Deep Dive (객체 리터럴) (0) | 2024.12.05 |
09. 모던 자바스크립트 Deep Dive (타입 변환과 단축 평가) (0) | 2024.12.03 |
정규식 예제 (2) | 2024.11.20 |