객체를 봉인하는 방법

Object 내장 객체에는 객체를 다루기 위한 다양한 정적 메서드들이 포함되어 있습니다.
그 중에서도 앞서 설명한 속성 설명자와 연관성이 짙은 몇 가지 메서드들에 대해 알아보려고 합니다.

아래에 알아볼 메서드들은 모두 객체를 사용자가 임의로 확장하고 수정할 수 없도록 봉인하는 방법들을 제공하는 것들입니다.

Object.preventExtensions

객체가 확장될 수 있다는 것은, 객체에 새로운 구성요소를 추가할 수 있음을 의미합니다.
Object.preventExtensions([객체명]) 메서드를 사용할 경우 해당 객체는 더이상 확장이 불가능합니다.

이 메서드는 객체의 확장가능성을 비가역적으로 막아버리기 때문에,
한 번 확장 불가능하도록 설정한 객체를 다시 확장이 가능하도록 되돌릴 수 없습니다.

Object.isExtensible

Object.isExtensible([객체명]) 메서드는 해당 객체가 확장이 가능한 객체인지 확인하여 불리언값을 반환합니다.

Object.freeze

Object.freeze([객체명]]) 메서드는 이름 그대로 해당 객체를 얼려버립니다.

  • 얼려진 객체는 확장이 불가능합니다.
  • 얼려진 객체의 속성들은 삭제가 불가능합니다.
  • 얼려인 객체의 속성들은 내부속성을 수정하는 것이 불가능합니다.
  • 얼려진 객체의 속성들은 새로운 값의 할당이 불가능합니다.

Object.isFrozen

Object.isFrozen([객체명]) 메서드는 해당 객체가 얼려진 객체인지 여부를 불리언값으로 반환합니다.

얼려진 객체의 내부

Object.freeze 메서드는 다음 코드와 같은 기능을 수행합니다.

function Freeze(obj) {
  const props = Object.getOwnPropertyNames(obj);

  // 확장이 불가능하도록 설정
  Object.preventExtensions(obj);

  // 모든 속성들에 대하여 configurable, writable을 false로 설정.
  props.map(one =>
    Object.defineProperty(obj, one, { writable: false, configurable: false })
  );

  return obj;
}

const target = {
  prop1: 1,
  prop2: {
    prop2_1: 2
  }
};

const result = Object.isFrozen(Freeze(target));
console.log(result); // 출력 : true

Object.seal

Object.seal([객체명]]) 메서드는 해당 객체를 봉인합니다.

  • 봉인된 객체는 확장이 불가능합니다.
  • 봉인된 객체의 속성들은 삭제가 불가능합니다.
  • 봉인된 객체의 속성들은 내부속성을 수정하는 것이 불가능합니다.
  • 하지만 각 속성에 새로운 값을 할당할 수 있습니다

Object.isSealed

Object.isSealed([객체명]) 메서드는 해당 객체가 봉인된 객체인지 여부를 불리언값으로 반환합니다.

Object.isSealed([객체명]) 메서드는 객체의 확장가능성과, 각 속성의 configurable 값이 false인지 여부만 검사합니다.

따라서, Object.freeze([객체명])으로 얼려진 객체에 대해서도 true값을 반환합니다.

객체의 봉인된 상태는 얼려진 상태의 부분집합과도 같습니다.

봉인된 객체의 내부

Object.seal 메서드는 다음 코드와 같은 기능을 수행합니다.

function Seal(obj) {
  const props = Object.getOwnPropertyNames(obj);

  // 확장이 불가능하도록 설정
  Object.preventExtensions(obj);

  // 모든 속성들에 대하여 configurable만을 false로 설정.
  props.map(one =>
    Object.defineProperty(obj, one, { configurable: false })
  );

  return obj;
}

const target = {
  prop1: 1,
  prop2: {
    prop2_1: 2
  }
};

const result = Object.isSealed(Seal(target));
console.log(result); // 출력 : true

위 메서드들은 모두 비가역적인 결과를 초래합니다

확장가능성을 막아둔 객체를 다시 확장가능하도록 되돌리는 방법은 없습니다.
또한, configurable이 false로 설정된 객체들에 대해 내부속성의 재정의가 불가능합니다.

따라서, 위 메서드들은 모두 한 번 수행되고나면 절대로 원 상태로 되돌릴 수 없습니다.