javascript

객체 변경 방지

noAb 2024. 6. 28. 21:39

프로퍼티 애트리뷰트

객체의 프로퍼티에는 자동으로 프로퍼티 애트리뷰트가 생성이 되는데 모든 속성은 true가 되며 변경 가능, 열람 가능, 재정의 가능 상태가 됩니다.

 

객체에 프로퍼티를 넣는 과정에서 Object.defineProperty메서드를 사용해 정의하면 변경이 가능하다.

이미 정의되어 있는 프로퍼티의 애트리뷰트를 수정하기 위해서 3가지 메서드가 제공이 됩니다.


객체 프로퍼티 애트리뷰트 수정 메서드

  1. Object.preventExtensions
  2. Object.seal
  3. Object.freeze

첫번째, Object.preventExtensions는 객체 프로퍼티 추가 X, 삭제 O, 읽기 O, 값 사용 O,애트리뷰트 재정의 O

두번째, Object.sea는 객체 프로퍼티 추가 X, 삭제 X, 읽기 O, 값 사용 O, 애트리뷰트  재정의 X

세번째, Object.freeze는 객체 프로퍼티 추가 X, 삭제 X, 읽기 O, 값 사용 X, 애트리뷰트  재정의 X


Object.preventExtensions ( 추가 X, 삭제 O, 읽기 O, 값 사용 O, 애트리뷰트 재정의 O )

const person = { name : 'Lee' };

// 확장 가능한 객체인지 확인하는 메서드
console.log(Object.isExtensible(person)); // true

Object.preventExtensions(person);

console.log(Object.isExtensible(person)); // false

person.age = 20; // 추가 X

delete person.name; // 삭제는 가능

console.log(Object.keys(person)); // []

Object.defineProperty(person,'age',{value:20}); // 메서드 이용해도 추가 X, 에러발생

 

Object.seal ( 추가 X, 삭제 X, 읽기 O, 값 사용 O, 애트리뷰트 재정의 X )

- 기본적으로 seal로 된 객체는 configurable이 fasle입니다.

const person = { name : 'Lea' };

// 객체가 seal 상태인지 확인하는 메서드
console.log(Object.isSealed(person)); // false

Object.seal(person);

console.log(Object.isSealed(person)); // true

person.age = 20; // 추가 X

person.name = 'Kim'; // 변경 가능

console.log(Object.keys(person)); // ['name']

Object.defineProperty(person,'name',{configurable : true}); // 애트리뷰트 재정의 X, 에러발생

 

Object.freeze

- 기본적으로 freeze로 된 객체는 writable, configurable이 fasle입니다.

const person = { name : 'Lee' };

// freeze객체인지 확인
console.log(Object.isFrozen(person)); // false

Object.freeze(person);

console.log(Object.isFrozen(person)); // true

person.age = 20; // 추가 X

person.name = 'Kim'; // 변경 X

console.log(person); // { name: 'Lee' }

Object.defineProperty(person,'name',{writable:true, configurable:true}); // 애트리뷰트 재정의 X, 에러발생

 


불변 객체

위 3가지 메서드는 지정된 객체에 대해서만 적용이 됩니다. 즉, 객체 안에 중첩으로 객체가 잇다면 해당 객체는 얼마든지 수정이 가능하게 됩니다. 특정 객체 하위에 모든 객체들에 영향을 주기 위해선 재귀함수를 사용해야합니다.

const person = { 
    name:'Lee' ,
    address : {
        city : 'seoul'
    }
};

console.log(Object.freeze(person));

console.log(Object.isFrozen(person)); // true

console.log(Object.isFrozen(person.address)); // false

function deepFreeze(target) {
    if (target !== null && (typeof target === 'object') && (!Object.isFrozen(target))) {
        Object.freeze(target);
        Object.keys(target).forEach(key => deepFreeze(target[key]));
    }
}

const person2 = {
    name : 'Kim',
    address : {
        city : 'Seoul'
    }
};

deepFreeze(person2);

console.log(Object.isFrozen(person2)); // true

console.log(Object.isFrozen(person2.address)); // true

Object.defineProperty(person2.address,'city',{value:'busan'}); // 에러발생