[JS] 원시타입과 참조타입

codeCYJ·2022년 6월 22일
0

javaScript

목록 보기
27/35

식별자 : 이름을 붙일 때 사용하는 단어(변수명,함수명,속성명,메소드명)
할당 : 식별자에 데이터를 넣는 행위
타입 : 식별자에 넣는 데이터값의 종류

JavaScript 의 변수타입

자바 스크립트의 데이터타입은 원시타입참조타입으로 나누어져 있다.

원시타입

가장 작은 데이터의 값.
객체가 아니면서 메소드도 가지고 있지 않은 더이상 쪼갤 수 없는 단위.

원시타입의 종류

string, number, bigint, boolean, undefined, null, symbol

원시타입의 데이터 할당

변수에 할당 시 메모리에 고정 크기로 값을 저장하고,
저장된 값의 주소를 변수가 직접적으로 가리키는 형태를 띈다.

let a = 1;
a = 2;


첫 라인이 실행되면 메모리에 1이라는 값이 생성되고, 변수 a는 1의 메모리 주소를 가리킨다.
두번째 라인이 실행되면 새로운 메모리에 새로운 2라는 값이 생성되고, 변수 a 가 가리키던 주소가 2의 값의 주소로 바뀌는것이다.
메모리에는 "1"과 "2"라는 모든 값이 존재하고 있는것.
그저 변수가 가르키는 주소가 바뀌었기때문에 재할당된것으로 보일 뿐이다.
이러한 경우 1이 담긴 메모리는 가비지 컬렉터에 의해 처리된다.

원시타입의 특징

  • 접근속도가 빠름.
  • 차지하는 메모리의 양이 참조타입에 비해 훨씬 적음.
  • 불변성을 가지고있음.

참조타입

참조타입이란?

자바스크립트에서 원시타입을 제외한 모든 것.(배열, 객체, 함수등)

참조타입의 할당

  • 크기가 정해져 있지 않은 값을 힙메모리라는 별도의 영역에 저장한다.
  • 값이 저장된 힙메모리의 주소를 변수의 값에 저장하고, 그 값의 주소를 변수가 가르키는 형태를 띈다.

깊은복사 vs 얕은복사

깊은 복사(Deep copy)란?

  • 데이터 자체를 통째로 복사한다.
  • 복사된 두 객체는 완전히 독립적인 메모리를 차지한다.
  • 원시타입의 객체들은 깊은 복사를 하게 된다.
let a = 1;
let b = a;
a = 2;

console.log(b) // 1

변수 b에 a를 할당 하게되면 변수 b의 메모리에 a의 값을 통째로 복사하여 담게 된다.
변수 a가 2로 재할당 되더라도(가르키는 주소가 바뀌더라도) b는 가르키는 주소가 다르기때문에 전혀 영향을 받지 않는다.

얕은 복사(Shallow copy)란?

  • 값을 복사했을때 메모리에 새로운 값을 생성하는 것이 아니라,
    주소값을 복사하여 같은 메모리의 주소를 가리키는 것.
  • 참조타입의 객체들은 얕은 복사를 하게 된다.

let myArr = [];
let copyArr = myArr;

myArr.push("hello");

console.log(copyArr); // ["hello"]

얕은 복사를 하게되면 같은 데이터의 주소를 가르키기 때문에,
하나의 값이 변경되면 같은 주소를 가르키는 다른 값도 같이 변경된다.

참조타입의 비교

let a = {};
let b = {}; // 독립된 두 객체
alert( a == b ); // false
alert( a === b ); // false

두 객체는 모두 비어있다는 점에서는 같아보이지만, 각각의 다른 주소를 가지고있는 독립된 객체이기 때문에 일치, 동등비교를 하면 거짓이 반환된다.

let a = {};
let b = a; // 참조에 의한 복사
alert( a == b ); // true, 두 변수는 같은 객체를 참조합니다.
alert( a === b ); // true

얕은 복사를 하게되면 a와 b는 같은 값의 주소를 가르키기 때문에 일치, 동등비교를 하면 참이 반환된다.

불변성(Immutability)

데이터가 생성된 이후 그 상태를 변경할 수 없는 것을 의미합니다.
재할당을 할 경우 새로운 메모리에 재할당한 값을 저장하고 새로운 메모리를 가르키는것일뿐 기존의 메모리에있는 값은 변하거나 사라지지않음.
<->
참조타입은 얕은 복사를 하기때문에, 객체 내부의 값을 변경하면
객체를 참조하고 있는 다른 값들도 다 같이 변경되므로 불변성 이슈가 생긴다.

참조타입의 깊은복사

  • 스프레드문법 (...)
  • Object.assign()
var coke = {
    name: 'coca',
    price: 2980,
}
var new_coke = {...coke};
coke.name = 'pepsi';
console.log(coke.name,new_coke.name);//'pepsi' 'coca'

스프레드 문법과 Object.assign() 은 1레벨 깊이에서만 유효하기 때문에 객체 내부의 객체의 불변성까지는 유지할수 없습니다.

  • JSON.parse && JSON.stringify
    JSON.stringify()는 객체를 json 문자열로 변환 후, JSON.parse()를 이용해 다시 원래 객체로 만들어줍니다.
const object = {
  a: "a",  
  number: {
    one: 1,    
    two: 2,  
  },  
  arr: [1, 2, [3, 4]]
}; 
const copy = JSON.parse(JSON.stringify(object)); 
copy.number.one = 3;
copy.arr[2].push(5); 
console.log(object === copy); //false
console.log(object.number.one === copy.number.one); // false
console.log(object.arr === copy.arr); // false 
console.log(object); 
// { a: 'a', number: { one: 1, two: 2 }, arr: [ 1, 2, [ 3, 4 ] ] }
console.log(copy); 
// { a: 'a', number: { one: 3, two: 2 }, arr: [ 1, 2, [ 3, 4, 5 ] ] }
  • 반복문과 재귀함수를 이용한 방법
  • lodash 라이브러리의 cloneDeep 사용

원시타입과 참조타입 차이

  • 원시타입은 콜스택에 데이터를 메모리의 고정 크기로 값을 저장되는 반면,
  • 참조타입은 메모리힙이라는 객체의 변수 영역이 추가로 존재하며 값의 크기가 동적으로 변한다는 것이다.

원시타입의 데이터(파란색 변수 a)

  • 10이라는 값 자체는 원시 타입이므로 콜 스택에 저장된다.
  • 변수 a에는 10이 저장된 콜 스택 메모리의 주소값이 저장된다.

참조 타입 데이터(핑크색 변수 b, c, d)

  • 배열, 객체, 함수 등은 참조 타입이므로 메모리 힙에 저장된다.
  • 참조타입 데이터가 저장된 메모리 힙의 주소값은 콜스택에 각각 저장된다.
  • 메모리힙의 주소 값이 저장된 콜 스택의 주소값은 각각 변수 b, c, d에 저장된다.

참고 자료
https://velog.io/@nomadhash
https://velog.io/@ellyheetov
https://velog.io/@welloff_jj
https://charming-kyu.tistory.com/19

cf)

콜스택
원시타입이 저장되는 공간.(함수 호출도 이곳에 저장된다.)
실행 콘텍스트(Execution Context)를 통해
1) 변수 식별자(이름) 저장,
2) 스코프 체인 및 this 관리,
3) 코드 실행 순서 관리 등을 수행.

메모리힙
참조 타입(객체 등) 데이터가 저장된다.
메모리 할당이 일어나는 곳.

profile
안녕하세요

0개의 댓글