[JS딥다이브] 5. 객체, 원시값과의 비교

게코젤리·2023년 4월 19일

객체 리터럴


1. 객체란?

  • 자바스크립트에서 원시 값을 제외한 모든 값.
  • 원시값은 불변(immutable), 객체는 변경이 가능한 값(mutable)
const obj = {
	num : 0, // -> 프로퍼티 (key, value)
  	increase: fuction(){ // -> 메서드
		this.num++;
	}
}

2. 프로퍼티

  • 식별자 네이밍을 따르지 않는 key는 ''로 감싸주어야 한다.
const obj = { 'a b' : 1 }
obj['a b']; // -> 1
  • 프로퍼티 키 동적으로 생성
const key = 'car';
const obj = { [key] : 1 }
obj; // -> { car : 1}
  • 키에 숫자타입을 사용하면 문자열로 변환된다.
  • 키를 중복 선언하면 나중에 선언한 프로퍼티로 덮어쓴다.

3. 메서드

  • 객체에 묶여있는 함수.

4. 객체 리터럴의 확장 기능

  • 프로퍼티 축약 : 프로퍼티 value로 사용할 변수와 프로퍼티 key가 동일한 이름일 때 축약 가능
const x = 1, y = 2;
const obj = { x, y } // > {x: 1, y: 2}
  • 메서드 축약
const obj = {
  name: "Lee",
  sayHi() {
    console.log("Hi!" + this.name);
  },
};
// 메서드 축약 표현으로 정의한 메서드는 프로퍼티에 할당한 함수와 다르게 동작한다는 것을 유의

원시 값과 객체의 비교


1. 차이점

  • 원시타입은 변경 불가능한 값, 객체(참조)타입은 변경 가능한 값
  • 원시 값을 변수에 할당하면 변수에는 실제 값이 저장, 객체를 변수에 할당하면 변수에는 참조 값이 저장.
  • 원시 값을 갖는 변수를 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달 -> pass by value
  • 객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달 -> pass by reference
  • 하지만 엄격하게 표현하면 변수에는 값이 전달되는 것이 아니라 메모리 주소가 전달된다. 식별자는 값이 아니라 메모리 주소를 기억하고 있기 때문

2. 원시 값

  • 변수에 원시 값을 할당하면 새로운 메모리 공간을 확보하고 원시 값을 저장한 후, 식별자는 새로운 메모리 공간을 기억한다.
  • 다른 원시 값을 재할당해도 위와 같은 과정이 계속 일어날 뿐, 원시 값 자체는 절대 변하지 않는다. 더 이상 참조되지 않는(식별자가 기억하지 않는) 메모리 공간의 값은 가비지 컬렉션에 의해 제거된다.
  • 문자열은 유사 배열 객체지만 결국 값을 변경할 수 없다.
  • 변수에 원시 값을 갖는 변수를 할당하면 서로 다른 메모리 공간에 저장된 별개의 값이 되어 서로 간섭할 수 없다.

👀 유사배열 객체

  • 배열처럼 인덱스로 프로퍼티값에 접근할 수 있고 length 프로퍼티를 갖는 객체.
  • name[0] = "k"은 에러가 나지 않지만 값은 변경되지 않는다.
  • 배열 메서드를 사용하면 에러가 난다.
  • DOM 조작시 querySelectorAll로 가져온 NodeList도 유사배열 객체다.

3. 객체

변수에 객체를 할당했을 때

  1. 변수에 객체를 할당하면 메모리의 두 공간을 확보한다.
  2. a공간에 실제 객체를 저장하고 b공간에는 객체가 저장된 공간을 가리키는 참조 값을 저장한다.
  3. 식별자는 참조 값을 기억한다.
  • 식별자 -> 메모리에 저장된 참조 값(객체의 위치 정보) -> 해당 위치에 저장된 객체
  • 객체를 가리키는 변수를 다른 변수에 할당하면 객체가 저장된 공간이 복사되는 것이 아니라 참조 값이 복사되어 전달된다. 결과적으로 각각의 변수는 같은 객체를 가리키게 된다.

구조적 이유와 문제점

  • 객체는 크기가 매우 클수도 있고 일정하지 않기 때문에 객체를 변경할 때마다 원시 값처럼 이전 값을 복사해서 새롭게 생성한다면 성능에 문제가 생길 수 있다.
  • 생성 비용을 절약하여 성능을 향상 시키기 위해 객체는 변경 가능한 값으로 설계
  • 그러나 위와 같은 이유로 객체는 여러개의 식별자가 하나의 객체를 공유할 수 있다는 단점이 있다.

해결 방법, 얕은 복사와 깊은 복사

  1. 얕은 복사 : 객체의 첫 번째 레벨(1단계)의 속성만 복사
    • 스프레드 문법
    • Array.slice()
    • Array.concat()
  2. 깊은 복사 : 얕은 복사의 경우 프로퍼티의 value가 객체일 경우 그 객체를 공유하게 되는 문제가 생긴다. 반면 깊은 복사는 객체의 모든 레벨(여러 단계)의 속성을 완전히 복사한다.(하위 객체가 없다면 얕은 복사로도 충분하다는 뜻이기도 하다)
    • JSON.parse()와 JSON.stringify()

📖 모던자바스크립트 딥다이브 10장 객체 리터럴(124p), 11장 원시 값과 객체의 비교(137p)

0개의 댓글