Language/JavaScript

[javascript]객체 변경방지

Hoplin 2021. 12. 14. 20:12
반응형

Object,즉 객체는 변경이 가능한 값이다. 프로퍼티를 삭제, 읽기, 갱신, 쓰기, 재정의 등을 할 수 있다. 자바스크립트에서는 이 객체의 가변성에 제한을 줄 수 있는 메소드들을 제공한다. 아래와 같이 세가지가 존재한다

구분 메소드 프로퍼티 추가 프로퍼티 삭제 프로퍼티 값 읽기 프로퍼티 값 쓰기 프로퍼티 어트리뷰트 재정의
객체 확장금지 Object.preventExtensions X O O O O
객체 밀봉 Object.seal X X O O X
객체 동결 Object.freeze X X O X X

 

객체 확장 금지

객체 확장 금지는 Object.preventExtensions메소드로 객체 확장을 금지한다. 객체 확장을 금지한다는 것은 프로퍼티 추가하는것이 제한된다는 것을 의미한다. 프로퍼티 동적 추가, Object.defineProperty()모두 포함이 된다. Object.isExtensibel()로 확장 가능한지 확인할 수 있다.

 

//객체 확장 방지

const person = {name : "Lee"};

//Object.isExtensible() : 객체가 확장 가능한지를 확인한다. bool타입을 반환한다.
console.log(Object.isExtensible(person)); // true
//Object.preventExtensions : 프로퍼티 추가를 금지한다. 프로퍼티 삭제, 값 읽기, 값 쓰기, 어트리뷰터 재정의는 가능하다
Object.preventExtensions(person);
console.log(Object.isExtensible(person)); // false

person.age = 30; // 무시된다.
console.log(person); // age프로퍼티가 추가되지 않은것을 볼 수 있다.

객체 밀봉

객체 밀봉은 Object.seal메소드로 밀봉할 수 있다. 밀봉된 객체는 추가는 물론이고, 객체의 읽고 쓰기만 가능해지게 된다. Object.isSearled()를 사용해서 밀봉되었는지 확인할 수 있다.

// 객체 밀봉

const person2 = {name : "Yoon"};
// Object.isSealed() : 객체가 밀봉되었는지를 확인한다 마찬가지로 bool타입을 반환한다.
console.log(Object.isSealed(person2));
// 프로퍼티를 밀봉한다. 프로퍼티 추가, 프로퍼티 삭제, 프로퍼티 재정의를 금지한다.
Object.seal(person2)
console.log(Object.isSealed(person2));

console.log(Object.getOwnPropertyDescriptor(person2,'name')); // configurable(재정의 여부)가 false인것을 알 수 있다.
/* Cannot redefine propery "name"
Object.defineProperty(person2,'name',{
    value : "Park",
    writable :  true,
    enumerable : true,
    configurable : true
});
*/

/*TypeError: Cannot define property age, object is not extensible
Object.defineProperty(person2, 'age',{
    value : 20,
    writable : true,
    enumerable : true,
    configurable : true
});
*/
/* Cannot redefine
Object.defineProperty(person2, 'name', {
    configurable : true
})*/
console.log(person2)

객체 동결

객체 동결은 프로퍼티 추가 및 삭제, 프로퍼티 어트리뷰트 재정의, 값 쓰기 모두 제한되며 오로지 읽기만 가능한 상태이다. Object.freeze메소드로 동결을 할 수 있으며, Object.isFrozen()으로 동결되었는지 확인 가능하다

//객체 동결 :  프로퍼티 값 읽기만 가능하며, 프로퍼티 추가, 프로퍼티 삭제, 값쓰기, 프로퍼티 어트리뷰트 재정의 모두 불가능하다.

const person3 = {name : "Yoon"}

console.log(Object.isFrozen(person3));
Object.freeze(person3);
console.log(Object.isFrozen(person3));
console.log(Object.getOwnPropertyDescriptor(person3, 'name'))
person3.age = 30; //무시된다
console.log(person3);

/*
Object not extensible

Object.defineProperty(person3, 'age',{
    value: 30,
    writable : true,
    configurable : true,
    enumerable : true
})
*/

불변 객체

위 세가지 객체 밀봉, 객체 확장금지, 객체 동결은 모두 얕은 범위에 대해서만 적용한다. 이말은 즉슨 중첩 범위에 대해서는 적용하지 못한다는 것이다. 중첩범위까지 모두 동결 / 확장금지 / 밀봉을 하고 싶다면 재귀적으로 객체들에 대해서 변경 방지 작업을 해주면 된다.

function deepFrozen(target){
    if(target && typeof target === "object" && !Object.isFrozen(target)){
        Object.freeze(target);
        Object.keys(target).forEach(key => deepFrozen(target[key]));
    }
    return target;
}

const person5 = {
    name : "Lee",
    address : {
        city : "Seoul"
    }
};

deepFrozen(person5);
console.log(Object.isFrozen(person5));
console.log(Object.isFrozen(person5.address));
person5.address.city = "Busan";
console.log(person5); // 변경되지 않음
console.log(Object.getOwnPropertyDescriptors(person5.address))
반응형