const키워드로 선언된 데이터타입들은 데이터주소를 재참조하지 못한다.
const value1 = 1;
let value2 = 1;
value1 = value2; //Uncaught TypeError: Assignment to constant variable!!!
에서 value1과 value2는 같은 데이터주소를 참조(reference)하고 있다. (Stack에서..), 즉 원시자료형같은 경우는 데이터의 효율적인 사용을 위해 값이 같을 경우에 데이터주소를 같이 참조한다. 해서 값이 같아도 데이터주소를 달리하여 데이터낭비(?)를 막기 위함으로 생각하면 좋다.
그렇다면 const키워드로 선언된 데이터타입들은 다른 데이터주소를 재참조하지 못하는 것이 아니라, 데이터 주소가 같더라고 그저 데이터주소를 재참조 하지 못하도록 하는 키워드라고 생각하면 좋겠다.
value1 = value2; //Uncaught TypeError: Assignment to constant variable!!!
하지만 참조자료형 같은 경우는 const로 선언되어도 property의 값을 변경할 수 있다. 이유는 참조자료형은 데이터주소를 재참조하지 않고 같은 데이터주소에서 값만 변경할 수 있기 때문이다. (참조자료형은 Heap이란 데이터영역에 위치한다.)
const obj1 = {name: 'Kim', score: [1,2]};
obj1.name = 'Lee';
console.log(obj1.name) // expected output -> 'Lee'
그렇다면 참조자료형(배열, 객체, 함수)는 값을 변경하지 못하게 막을 순 없는 걸까?
-> 그런 기능을 위해 생긴 메소드는 바로..
객체를 얼려서 값변경을 하지 못하도록 하는 메소드라고 생각하면 편하다.
const obj1 = {name: 'Kim', score: [1,2]};
Object.freeze(obj1)
obj1.name = 'Lee';
obj1.score.push(3);
console.log(obj1.name);
// expected output -> 'Kim'
console.log(obj1.score);
// expected output -> [1, 2, 3]
obj1.name
은 Object.freeze(obj1)
로 인해 값이 변경되지 않는 걸 볼 수 있다, 하지만 obj1.score
는 push
로 왜 값이 추가될 수 있었을까?
참조자료형(배열, 객체, 함수)등은 property(속성)값 가지고 있다. 하지만 그 property가 또 다른 참조자료형의 위치를 가르키고 있다면 첫 참조자료형과 첫 참조자료형의 property중 그 property가 가진 참조자료형이 있다면 두 둘째 참조자료형과는 데이터주소가 다르다.
코드로 보여드리겠습니다..
let obj1 = {name: 'Kim', score: [1,2]};
let obj2 = Object.assign({}, obj1);
console.log(obj1 === obj2)
// expected output -> false
console.log(obj1.score === obj2.score)
// expected output -> true
여기서 obj1과 obj1.score의 데이터주소가 다르기 때문에 Object.assign()
을 할때에 obj1.name까지는 새로운 객체로 얇은 복사를 했지만, obj1.score는 obj1과 데이터주소가 달라서 깊은 복사가 되어버려서 obj1.score
와 obj2.score
가 같게 되는 것이다.
Object.freeze()
도 마찬가지로 obj1
와 obj1.score
의 데이터주소가 다르기 때문에 Object.freeze()
가 obj1.score
의 데이터주소까지 reference를 하지못해서, 즉 obj1.score
의 데이터주소의 주소까지 참조를 못해서 obj1.score
까지 값변경을 하지 못하도록 얼리지 못했다는 것이다.
// obj1뿐만아니라 obj1.score까지도 immutable하게 만듬
const obj1 = {name: 'Kim', score: [1,2]};
Object.freeze(obj1);
Object.freeze(obj1.score);
obj1.score.push(3); // 오류는 뜨지 않지만 적용되지 않음
// obj1.score과 obj2.score가 다른 데이터주소값을 갖도록 해주기위해서
// Object.assign을 한번 더해줌. (완전 얇은 복사가 됌)
const obj2 = Object.assign({}, obj1);
obj2.score = Object.assign({}, obj2.score);
console.log(obj1 === obj2);
// expected output -> false;
console.log(obj1.score === obj2.score);
// expected output -> false;
console.log(obj1.score);
// expected output -> [1, 2]
항생제가 미생물에 의해서 만들어진 물질로서 다른 미생물의 증식을 억제하거나 혹은 죽이는..
항생제가 발명되어 수많은 사람들을 살리고 현재까지도 그러한 것이 사실이지만, 남용을 하게되니 안좋다고 인식을 하게 되는 것처럼,.
인스턴트음식이 수많은 사람들을 기아에서 구출했지만 남용되어 인스턴트가 안좋은 음식이라고 생각할 수 있는 것처럼..
mutable도 안좋은 개념이 아니다. 잘 쓰면 상관없다. 하지만 남용되면 오류도 많아지고 어려워지므로 그 사용하는 의도와 상황을 파악해서 센스있게 mutable과 immutable을 사용하도록 하자.
불변함을 유지하는 것은 알아야할 것도 많고, 까다롭다.
그래서 라이브러리를 제공한다.
'immer'
npm install immer
'mori'