Title : JavaScript 객체와 불변성이란 ?
1)이를 알기 위해서는 '불변성'부터 알아야 한다.
변수와 상수는 '변수 영역 메모리에 데이터 할당 후 재할당'이 되는지에 대한 여부로 구분되는 것이며,
불변성은 '데이터 영역의 메모리에 대한 것'이다
데이터영역의 데이터는 한번 생성되었을경우 수정이 안되며,(불변성)
새로운 데이터일 경우 비어있는 데이터 영역에 새로 할당된다.
이떄, 변수는 데이터영역의 주소값을 재할당이 가능한것이고, 상수는 데이터 영역의 주소값 재할당이 불가능한것이다.
불변성은 재할당이 기준이 아니라, 데이터영역의 데이터가 변경가능한지에 대한 여부이다. 그래서 불가능하므로, 불변성인것이다.
2)기본형 타입(Primitive Type)과 참조형 타입(Reference Type)
여기서 포인트는 '객체의 변수(프로퍼티) 영역'의 유무이다.
참조형 타입도 기본형 타입과 마찬가지로 변수영역, 데이터 영역이 존재한다. 식별자 person 변수 영역에 데이터 영역 주솟값을 연결해줍니다.
하지만, 참조형 타입은 영역이 하나 더 존재하는데,
그게 바로 '객체의 변수(프로퍼티)'영역입니다.
데이터 영역 주솟값에 데이터가 바로 할당되는 것이 아니라, 객체의 프로퍼티 영역의 주솟 값(7000-7001)이 연결된다. 그리고 해당 객체의 프로퍼티 영역에 데이터 영역의 주솟값을 연결해준다. (name -5002/age-5003)
Value and Reference type
모든 데이터 타입은 값 타입(value type) 또는 참조 타입(reference type)을 가진다.
값 타입(Value type) : 각각의 고유의 메모리를 소유한다. 스위프트에서 struct, enum, array, tuples 들이 해당 타입에 속한다.
참조 타입(Reference type) : 생성된 인스턴스들은 주소값을 공유한다. 스위프트에서 class가 해당 타입에 속한다.
이렇게 기본형 타입과 참조형 타입을 알아보았다.
결론을 먼저 얘기하자면,
const와 Object.freeze()를 조합하여 만들 수 있다.
(const의 재할당불가 + Object.freeze()의 객체속성 변경불가)
자, 그럼 const와 Object.freeze()에 대해서 하나씩 알아보자.
1. const
자바스크립트 키워드 중 하나인 const이다. ES6문법부터 let과 const를 지원한다.
const 키워드는 변수를 상수로 선언할 수 있다, 일반적으로 상수로 선언된 변수는 값을 바꾸지 못하는 것으로 알려져 있다.
그렇다면 상수로 선언한 객체는 불변 객체일까?
ES6에서의 const는 할당된 값이 상수가 되는 것이 아닌 바인딩된 값이 상수가 되는, 즉 test변수가 상수가 되기 때문에 const 키워드로 선언된 test변수에는 객체 재할당은 불가능하지만 객체의 속성은 변경 가능하다.
재할당이 불가능 한 이유는 변수와 값(객체) 사이의 바인딩 자체가 변경이 되기 때문에 상수인 test변수는 재할당이 불가능한 것이고
객체의 속성이 변경가능 한 이유는 실제 객체가 변경은 되지만 ( {} -> name : "mingyo" ) 객체와 변수(test)사이의 바인딩은 변경이 되지 않기 때문에 객체의 속성은 변경가능한 것이다.
때문에 비록 재할당은 불가능하지만 객체의 속성을 변경함으로 인해 변수에 바인딩된 객체의 내용까지 변경이 되기 때문에 불변객체라고 하기는 힘들다. 따라서 Object.freeze()라는 JS내장메소드도 살펴보도록 하겠다.
2.Object.freeze()
자바스크립트에서 기본적으로 제공하는 메소드인 Object.freeze() 메소드이다. 공식 문서에서는 "객체를 동결하기 위한 메소드" 라고 적혀있다.
그렇다면 이 메소드를 사용하면 불변 객체를 만들 수 있을까?먼저 이 메소드의 사용법부터 알아보면,
사용법은 간단하다. test 변수에 key value를 가진 객체를 바인딩 후 Object.freeze(test)를 사용해 바인딩된 변수를 동결 객체로 만들었다. 때문에 test 객체는 객체의 속성을 변경하는 시도는 불가능하다.
그러나 Object.freeze()는 동결된 객체를 반환하지만 객체의 재할당은 가능하다.
위와 같이 객체의 재할당은 가능하다. 때문에 Object.freeze()도 불변 객체라고 할 수는 없을 것 같다.
그래서 1+2 =>불변객체를 만드는것이다.
이둘의 차이를 예시로 들어보자면,
일란성 쌍둥이는 깊은 복사,
이란성 쌍둥이는 얕은 복사로 예를 들 수 있다.
1.깊은 복사(Deep copy)란?
데이터 자체를 통째로 복사한다.
복사된 두 객체는 완전히 독립적인 메모리를 차지한다.
value type의 객체들은 깊은 복사를 하게 된다.
아래의 예시에서 arr1은 string 배열을 가진다. arr2에 arr1을 할당 해보자.
이때, arr1에 있는 모든 string들은 깊은 복사가 일어나서 새로운 배열을 생성하여 arr2에 할당한다. (String은 value type이므로 깊은 복사가 일어난다.) 때문에 arr1을 변경하여도 arr2에서는 값이 변경되지 않는다.
아니다. String은 깊은 복사가 일어나므로 string1을 변경하여도 string2는 변경되지 않는다.
이렇게 깊은 복사는 인스턴스가 완전히 독립적이다. 이와 같은 개념은 모든 value type에 적용된다.
2.얕은 복사(Shallow copy)란?
얕은 복사는 아주 최소한만 복사를 한다. 값을 복사한다 하더라도, 인스턴스가 메모리에 새로 생성되지 않는다. 값 자체를 복사하는 것이 아니라 주소값을 복사하여 같은 메모리를 가리키기 때문이다.
새로운 인스턴스를 생성하지 않기 때문에 깊은 복사보다 상대적으로 빠르다. reference type을 복사하는 경우 얕은 복사가 일어난다.
긴글 읽어주셔서 감사합니다^^