본문 바로가기

4. Programming/4.3 JavaScript

6. Immutability (객체와 변경불가성)


객체는 참조(reference) 형태로 전달하고 전달 받음. 

객체가 참조를 통해 공유되고 있다면, 그 상태가 언제든지 변경될 수 있기 때문에 의도치 않은 변경이 발생되어 여러가지 문제가 발생 될 수 있음. 


의도하지 않은 객체의 변경이 발생하는 원인의 대다수는 "레퍼런스를 참조한 다른 객체에서 객체를 변경"하기 때문.

객체를 불변객체로 만들어 프로퍼티의 변경을 방지하여 객체의 변경이 필요한 경우에는 참조가 아닌 객체의 방어적 복사를 통해, 새로운 객체를 생성 후 변경


또는, Observer 패턴으로 객체의 변경에 대처. 


1. immutable value vs. mutable value

javascript의 기본 자료형(primitive data type)은 변경 불가능한 값(immutable value). 

- Boolean

- null

- undefined

- Number

- String

- Symbol (ECMAScript 6) 


기본 자료형 이외의 모든 값은 객체(Object) 타입이며, 객체 타입은 변경 가능한 값(mutalbe value). 
즉, 새로운 값을 다시 만들 필요없이 직접 변경이 가능.


var text = 'Hello';
text = 'Bye';

console.log(text);


첫번째 구문이 실행되면, 메모리에 문자열 'Hello'가 생성, 식별자 text는 메모리에 생성된 문자열 'Hello'의 메모리 주소를 가르킴.

그리고 두번째 구문이 실행되면 이전에 생성된 'Hello' 문자열을 수정하는 것이 아닌, 새로운 문자열 'Bye'를 생성 후, 식별자 text가 가르키게 됨.

문자열 'Hello'와 'Bye'는 모두 메모리에 존재하는 상태가 됨.

var user = {
name: 'A',
address: {
city:'seoul'
}
};

var names = user.name; // A 할당
user.name = 'B';

console.log(typeof(names)); // String
console.log(names); // A
console.log(user.name); // B

user.name을 변경하였으나, 변수 names의 값은 변경되지 않음. 

변수 names 에 user.name을 할당할때, 참조를 할당하는 것이 아닌, String의 immutable한 값이 새로 생성되었고, 해당 값을 참조하기 때문.


var user = {
name: 'A',
address: {
city:'seoul'
}
};

var user1 = user; // user Object

user1.name = 'B';

console.log(user.name);
console.log(user1.name);

user2의 name의 프로퍼티에 새로운 값을 할당하면 객체는 변경 가능한 값이므로, user 객체도 변경 됨. 

이는 같은 address를 참조하고 있기 때문.

의도하지 않은 동작이라면 참조를 가지고 있는 다른 장소에 변경 사실을 통지 또는 대처하는 추가 대응이 필요.


2. 불변 데이터 패턴 (immutable data pattern)

의도하지 않은 객체의 변경이 발생하는 원인의 대다수는 레퍼런스를 참조한 다른 객체에서 객체를 변경하기 때문. 
객체를 변경 방지 또는 객체의 방어적 복사 (defensive copy) 를 통해 새로운 개겣를 생성한 후 변경.

2.1 Object.assign 

Object.assign은 타겟 객체의 프로퍼티를 복사하여, 결과 값으로 객체를 생성하여 반환.
ES6에서 추가된 메소드이며, Internet Explorer는 지원하지 않음.
var user = {
name: 'A',
address: {
city:'seoul'
}
};


const user1 = Object.assign({}, user); //user 객체를 user1에 저장.
console.log (user1 == user); //false
user 객체를 빈 객체에 복사하여, 새로운 객체 user1을 생성, user와 user1은 프로퍼티를 공유하지 않으므로, 변경 시에도 다른 객체에 영향을 주지 않음.

2.2 Object.freeze

Obejct.freeze()를 사용하여 불변의 객체로 만들 수 있음.
var user = {
name: 'A',
address: {
city:'seoul'
}
};

Object.freeze(user);
user.name = 'B'; // 무시
console.log(user);

uesr.address.city = 'Daejeon';
console.log(user.address.city); //객체의 내부 객체는 변경 가능함.

내부 객체까지 변경 불가능하게 만들기 위해서는 Deep Freeze를 해야 함. 


function deepFreeze(object) {
var propNames = Object.getOwnPropertyNames(object); // 객체의 key를 propNames에 배열로 저장

for (let name of propNames) { // 배열의 length만큼 반복
let value = object[name];

object[name] = value && typeof value === "object" ?
deepFreeze(value) : value;
}

return Object.freeze(object);
}

var user = {
name: 'A',
address: {
city:'seoul'
}
};

deepFreeze(user);



참고 : https://poiemaweb.com/

'4. Programming > 4.3 JavaScript' 카테고리의 다른 글

8. 타입 체크  (0) 2018.07.24
7. Function (함수)  (0) 2018.07.15
5. Object (객체)  (0) 2018.06.17
4. 제어문 (Control flow statement)  (0) 2018.05.28
3. Operator (연산자)  (0) 2018.05.12