🔖 11장, 원시 값과 객체의 비교
1
📌 배운 내용 및 기억하고 싶은 내용
원시 값
변경 불가능한 값, 읽기 전용 값
원시 값 자체를 변경할 수 없다(불변)
변수 값은 변경 할 수 있다
불변의 특성은 데이터의 신뢰성을 보장한다
상수는 재할당이 금지된 변수를 의미한다. 따라서 값을 변경할 수 없는 원시 값과는 다른 개념이다.
1
2
3
4
5
6
7
// const 키워드를 사용한 상수
const obj = {};
// const 키워드를 사용하여 선언한 변수에 할당한 원시 값(상수)은 변경 할 수 없다
// 하지만 const 키워드를 사용해 선언한 변수에 할당한 객체는 변경이 가능하다
obj.a = 1;
console.log(obj);
- 불변성을 갖는 원시 값을 할당한 변수는 재할당 이외에 변수 값을 변경할 수 있는 방법이 없다
- 문자열은 원시타입이므로, 불변성을 가지고 있으며 읽기 전용 값이고 재할당이 가능하다.
값에 의한 전달
- 자바스크립트는 하나에 변수에 값이 같더라도 다른 메모리 공간 값을 가르킨다
- 변수와 같은 식별자는 값이 아니라 메모리 주소를 기억하고 있기 때문에, 변수에는 값이 전달되는 것이 아니라 메모리 주소가 전달된다
- 두 변수의 원시 값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어 어느 한쪽에서 재할당을 통해 값을 변경하더라도 서로 간섭할 수 없다
객체
- 객체는 프로퍼티 개수가 정해져 있지 않다
- 동적으로 추가되며 삭제 가능 하다
- 프로퍼티의 값에 제약이 없다
- 자바스크립트 엔진은 클래스 기반 객체지향 프로그래밍 언어와 다르게 객체가 생성된 이후에도 동적으로 프로퍼티와 메서드를 추가 할 수 있지만, 생성과 프로퍼티 접근에 비용이 더 많이 들어 비효율적이다
- 프로퍼티에 접근하기 위해 동적탐색 대신 히든클래스 방식을 사용하여 성능을 보장한다.
변경 가능한 값
- 객체는 변경 가능한 값
- 참조 타입
- 객체에 할당한 변수는 재할당 없이 객체를 직접 변경할 수 있다
- 재할당 없이 프로퍼티를 동적으로 추가하고 프로퍼티 값을 갱신이 가능하며 프로퍼티 자체 삭제도 가능하다
- 메모리에 저장된 객체를 직접 수정 가능하지만, 객체에 할당한 참조값은 변경되지않는다.
- 객체를 생성하고 관리하는 방식은 매우 복잡하며 비용이 많이 든다 == 메모리 비효율적, 성능저하
- 메모리를 효율적으로 하기위해 변경 가능 한 값으로 설계됨
- 원시 값과 다르게 여러개의 식별자가 하나의 객체를 공유할 수 있다는 단점
- 얕은 복사와 깊은 복사
- 얕은 복사 : 한단계까지만 복사
- 깊은 복사 : 객체에 중첩되어 있는 객체까지 모두 복사
- 얕은 복사와 깊은 복사로 생성된 객체는 참조 값이 다른 별개의 객체
- 얕은 복사는 객체에 중첩되어 있는 객체일 경우 참조 값을 복사
- 깊은 객체는 객체에 중첩되어있는 객체까지 모두 복사 == 완전한 복사본
- 원시 값을 할당한 변수를 다른 변수에 할당 == 깊은복사
- 객체에 할당한 변수를 다른 변수에 할당 == 얕은 복사
참조에 의한 전달
- 참조 값이 복사되어 전달
- 두 개의 식별자가 하나의 객체를 공유
- 자바스크립트에서 참조에 의한 전달은 존재 하지 않는다 => 공유에 의한 전달
1
❗️ 읽은 소감
자바와 C++에서의 객체는 동적으로 프로퍼티 생성, 삭제가 안되지만, 자바스크립에서는 동적으로 프로퍼티 생성과 삭제가 된다는 차이가 있다는 점의 차이점을 알게 되었다. 또한 객체는 변경 가능한 값이기 때문에 변수 obj1을 얕은 복사하여 obj2에 할당하여 두개의 변수중 하나를 객체값을 변경한다면 다른 하나도 객체값도 변경되는 문제가 있기 때문에, 복사를 통해 해결해야겠다는 생각이 들었다.
1
❓ 궁금한 내용이나 잘 이해되지 않는 내용
얕은 복사(Shallow Copy)
Object.assign(target, source)
1 2 3 4 5 6
const original = {name: '세진', age: 13}; const clone = Object.assign({}, original); clone.name = '강호' console.log(original) // {name: '세진', age: 13} console.log(clone); // {name: '강호', age: 25}
Spread Operator
1 2 3 4 5 6 7 8 9
const original = {profile: {name:'세진', age:13}, grade: 'A+'}; const clone = { ...original }; clone.profile.name = '강호'; clone.grade = 'B'; // clone의 내부 객체인 profile은 original의 profile과 동일한 주소를 참조 console.log(original) // {profile: {name: '세진', age: 13}, grade: 'A+'} console.log(clone); // {profile: {name: '세진', age: 13}, grade: 'B'}
깊은 복사(Deep Copy)
JSON.stringify()
&JSON.parse()
(객체 -> 문자열 변환) & (문자열 -> 객체 변환)1 2 3 4 5 6 7 8 9
const original = {profile: {name:'세진', age:13}, grade: 'A+'}; const clone = JSON.parse(JSON.stringify(original)); clone.profile.name = '강호'; clone.grade = 'B'; // JSON 속도 최적화는 되어있지만, 복잡한 객체에 대해서는 처리 속도가 느리다 console.log(original) // {profile: {name: '세진', age: 13}, grade: 'A+'} console.log(clone); // {profile: {name: '강호', age: 13}, grade: 'B'}
_.cloneDeep(value)
- lodash 라이브러리 사용
structuredClone(value)
- 일부 브라우저에서 지원