(8) 심플한데 복잡하고 컴플리케이티드한데 간단한 원시자료형 VS 참조자료형

데인·2022년 11월 7일
1

Study with Me

목록 보기
8/12

데이터를 저장하는 방식에 따른 분류

number, string, boolean, null, undefined와 같은 고정된 저장공간을 차지하는 데이터 = 원시자료형 ⇒ 값(데이터)을 저장한다

대량의 데이터를 다루기에 적합한 배열, 객체 = 참조자료형 ⇒ 데이터가 담긴 저장소의 주소를 저장한다.

원시 자료형

  • 변수에는 하나의 데이터(값)만 담는다.
  • 값 자체에 대한 변경이 immutable, 변수에 다른 데이터를 할당 가능. (값 자체에서 뺐다 넣었다 불가, 변수에 다른 데이터 할당을 통해 가능) (원시 값 자체를 변경할 수 없다는 것, 변수 값을 변경할 수 없다는 것이 아님.
    변수는 언제든지 재 할당을 통해 변수 값을 변경(사실은 교체)할 수 있다. 상수는 재 할당 금지됨 (예를들어 const , but const에 할당한 객체는 값 변경 가능 (주소만 가져왔기 때문))
"hello world!"
"hello codestates!"
// "hello world!" 와 "hello codestates!"는 모두 변경할 수 없는 고정된 값입니다.

let word = "hello world!"
word = "hello codestates!"
// 하지만, word라는 변수에 재할당을 하여 변수에 담긴 내용을 변경하는 것은 가능합니다.

const num1 = 123;
num1 = 123456789; // 에러 발생
// const 키워드로 선언하면, 재할당은 불가합니다.
  • 원시 값은 number, string, boolean, null, undefined가 있는데 값을 저장하려면 먼저 확보해야 하는 메모리 공간의 크기를 결정해야함 ⇒ 우와 근데 타입별로 크기가 정해져 있네!(아, 숫자, 문자열만.., 나머지는 브라우저마다 다름)
  • 숫자는 1도, 1000000도 8바이트가 필요한데 문자열은 1개당 (약)2바이트가 필요함.
  • 엄밀히 말하면 변수에는 값이 전달되는게 아니라 ‘메모리 주소’가 전달된다.(그러나 메모리 주소 = 값)일 정도로 밀접하므로 값이라고 이해하는게 편할 뿐이다.
    • 어? 그럼 참조 자료형이랑 다른게 뭐예요?
      = 변수에 원시 값을 갖는 변수를 할당하면 변수 할당 시점이든 두 변수 중 어느 하나의 변수에 재 할당하는 시점이든 결국 두 변수의 원시 값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어 어느 한 쪽에서 재할당을 통해 값을 변경하더라도 서로 간섭할 수 없다.

참조 자료형

  • 여러 데이터가 heap이라는 데이터 보관함에 담기게 된다. ⇒ 이 heap의 주소가 변수에 담긴다.
  • heap은 사이즈를 다이나믹하게 동적으로 늘렸다가 줄였다가 한다.
    객체는 크키가 매우 클 수 도 있고, 원시값처럼 크기가 일정하지 않고, 프로퍼티 값이 객체일 수 있어 복사하고 생성하는 비용이 크다. = 메모리의 효율적 소비가 어렵고 성능이 나빠진다.
    ⇒ 그래서 객체 값을 변경 가능하게 설계한 것.(아 ㅋㅋ 그 안에서 지지고 볶고 하라고ㅋㅋ)
  • 근데 단점이 있음. 원시값과 달리 여러 개의 식별자가 하나의 객체를 공유 원본과 사본 중 한 쪽에서 객체를 변경하면 서로 영향을 주고받는다.
**var person = {
    name: 'Lee'
}
var copy = person;
console.log(copy === person); //true

copy.name = 'Kim'
person.address = 'Seoul'

console.log(person) //{name: 'Kim', address: 'Seoul'}
console.log(copy) //{name: 'Kim', address: 'Seoul'}
------------------------------------------------------------------
var person1 = {
    name: 'Lee'
}
var person2 = {
    name: 'Lee'
}

console.log(person1 === person2) 
//변수에 저장되어 있는 값(참조 주소)을 타입 변환하지 않고 비교, false
console.log(person1.name === person2.name) //true**

얕은 복사와 깊은 복사

얕복, 깊복으로 만들어진 객체는 원본과는 다른 객체다.(참조값이 달라!)

  • 얕은복사 = 원본 데이터를 얇게 저며서 쓴다고 생각하자..(?)
    객체를 프로퍼티 값으로 갖는 객체의 경우, 한 단계까지만 복사
  • 깊은 복사 - 그냥 전체 다 복사.
const o = {x:{y: 1}};

//얕은복사
const c1 = {...o};
console.log(c1) // {x:{y: 1}}
console.log(c1 === o) //주소 비교, false
console.log(c1.x === o.x) //값 비교, true

//깊은복사
const_ = require('lodash')

const c2 = _.cloneDeep(o) //깊은복사 해준 것.
console.log(c2 === o) //주소 비교
console.log(c2.x === o.x) //값 비교

왜 heap은 동적으로 변하는가

  • 배열과 객체는 대량의 데이터를 쉽게 다루기 위해서 사용된다 ⇒ 크기가 고정되어있지 않고 우리가 데이터를 추가하고 삭제하는 것에 따라서 크기가 달라진다.
profile
너무나 바쁜 걸 아직 갈 데가 많아 난. 호기심 가득한 세상을 다 펼쳐볼거야. Chase Me! - Dreamcatcher

0개의 댓글