(ES5의 메소드이다.)
Object.freeze의 기능은 객체든 프로퍼티든 상수로 만드는 것이다.
즉, 값을 변경하지 못하게 하는 기능이다.
const OBJ2 = {
prop1: 1
}
Object.freeze(OBJ2);
OBJ2.prop1 = 10;
console.log(OBJ2.prop1); // 1
근데 여기서 문제가 있다. 만약 OBJ2의 프로퍼티가 배열이라면 배열의 요소들은 변경이 가능하다는 것이다.
const OBJ2 = {
prop1: 1,
prop2: [1, 2, 3]
}
Object.freeze(OBJ2);
OBJ2.prop2 = 10;
console.log(OBJ2.prop2); // [1, 2, 3]
OBJ2.prop2[1] = 20
console.log(OBJ2.prop2); // [1, 20, 3]
[데이터 도식화]
왜 OBJ2.prop2 배열들의 요소들은 바꿀 수 있는 것일까?
freeze를 하면 prop1과 prop2가 가리키고 있는 @60, @50 이 고정되는 것이다.
prop2는 @50을 가리키고 있지만, 배열 요소들의 값들은 또 다른 주소를 참조하고 있으므로 고정되어 있지 않다.
Object.freeze(OBJ2.prop2)
배열에 해당하는 프로퍼티인 prop2를 freeze시켜야 한다.
그렇게 되면 배열 요소들의 값을 참조하는 주소가 freeze되어 값을 변경할 수 없게 된다.
즉, 위의 도식화에서는 200~202에 들어있는 prop2의 요소들의 값의 주소가 고정되는 것이다.
위와 같이 객체안에 또 객체가 있는 경우가 있을 것이다.
객체안의 객체까지 모두 freezing 하는 것을 DeepFreezing이라고 한다.
방법
1. 부모객체를 freezing한다.
2. 내부의 프로퍼티들을 순회하면서, 1을 반복하며 재귀한다.
Object.assign(target, ...sources)
이를 이용하여 복사할 수 있다.
- target
목표 객체. 출처 객체의 속성을 복사해 반영한 후 반환할 객체입니다.- sources
출처 객체. 목표 객체에 반영하고자 하는 속성들을 갖고 있는 객체들입니다.
얕은복사 예제
var a = {
a: 1,
b: [1, 2, 3],
c: { d: 1, e: 2}
}
var b = Object.assign({},a);
b.b[1] = 20;
console.log(a.b); // [1, 20, 3]
위의 예시처럼 복사한 b의 객체의 요소를 바꾸면 복사대상인 a의 요소의 값도 바뀌어 버린다.
즉, 같은 값을 참조하는 것이다.
데이터 도식화를 통해서 복사되는 과정을 자세히 알아보자.
[a의 데이터 도식화]
[b의 데이터 도식화]
b가 a를 복사하면 a의 객체에 해당하는 @100~102를 복사한다.
이것을 b의 새로운 공간인 @121~123에 저장한다.
그러므로 b.a의 값을 바꾸어도 a.a의 값이 변하지는 않지만, b.b[1]의 값을 바꾸면 a.b와 가리키는 주소가 같으므로 a.b의 값도 변하게 되는 것이다.
a.b의 값도 변하지 않게 하려면 깊은복사를 해야한다.
깊은복사란 모든 depth에 대해서 객체의 프로퍼티들을 복사하는 것이다.
아까 얕은복사에서 복사대상인 a의 값들을 변경하지 않게 하려면 어떻게 해야할까?
b.b[1] = 20으로 해도 a.b의 값이 2를 유지하게 하려면 다음과 같이해야한다.
var a = {
a: 1,
b: [1, 2, 3],
c: { d: 1, e: 2}
}
var b = Object.assign({},a);
b.b = Object.assign([], a.b);
b.b[1] = 20;
console.log(a.b); // [1, 20, 3]
[b.b의 데이터 도식화]
b.b를 복사했으므로 @220~222에 새로운 공간을 만들어 a.b의 내용을 넣어준다.
a.b의 내용은 @200~에 있으므로 b.b의 내용을 바꾸어도 영향을 받지 않는다.
깊은복사를 해야만 immutable하다.
깊은복사를 해야만 기존객체와 동떨어진 객체를 생성할 수 있다는 뜻이다.