하루 30분 모던 자바스크립트 딥 다이브. 프로퍼티 어트리뷰트

내부 슬롯과 내부 메서드

  1. 내부 슬롯과 내부 메서드는 자바스크립트 엔진의 구현 알고리즘을 설명하기 위해 ECMAScript 사양에서 사용하는 의사 프로퍼티와 의사 메서드다. 이중 대괄호 ([[…]]) 내부 슬롯과 내부 메서드다.
  2. 내부 슬롯과 내부 메서드에 직접적 접근하거나 호출할 수 있는 방법을 제공하지 않는다. 단 일부 내부 슬롯과 내부 메서드에 한하여 간접적으로 접근할 수 있는 수단을 제공하기는 한다. ex) [[Prototype]] 내부 슬롯은 __proto__를 통해 간접적으로 접근 가능.

프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체

  1. 자바스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티 상태를 나타내는 어트리뷰트를 기본값으로 자동 정의한다.
    1. 프로퍼티의 값 [[Value]]
    2. 값의 갱신 가능 여부 [[Writable]]
    3. 열거 가능 여부 [[Enumerable]]
    4. 재정의 가능 여부 [[Configurable]]
  2. Object.getOwnPropertyDescriptor 메서드
    1. 호출할 때 첫 번째 매개변수에는 객체의 참조를 전달, 두 번째 매개변수에는 프로퍼티 키를 문자열로 전달한다.
    2. 프로퍼티 디스크립터 객체를 반환한다. 만약 존재하지 않는 프로퍼티나 상속받은 프로퍼티에 대한 디스크립터를 요구시 undefined반환.
  3. 데이터 프로퍼티와 접근자 프로퍼티
    1. 데이터 프로퍼티
      1. 키와 값으로 구성된 일반적인 프로퍼티.
      2. 기본값으로 프로퍼티의 값 [[Value]], 값의 갱신 가능 여부 [[Writable]], 열거 가능 여부 [[Enumerable]], 재정의 가능 여부 [[Configurable]]가 자동 정의.
      3. Value는 값으로, 나머지는 기본값 true로 초기화된다.
    2. 접근자 프로퍼티
      1. 자체적으로는 값이 없지만 다른 데이터의 값을 읽거나 저장하는 접근자 함수로 구성된 프로퍼티.
      2. getter함수 [[Get]], setter함수 [[Set]], [[Enumerable]], [[Configurable]]를 가진다.
      3. Object.getOwnPropertyDescriptor 메서드가 반환하는 프로퍼티 디스크립터 객체의 get 프로퍼티 값과 같다.
  4. 프로퍼티 정의
    1. Object.defineProperty 메서드를 프로퍼티의 어트리뷰트를 정의할 수 있다.
    2. Object.defineProperties 메서드는 여러 개의 프로퍼티를 한 번에 정의할 수 있다.

    프로퍼티 디스크립터 객체의 프로퍼티   대응하는 프로퍼티 어트리뷰트 생략시 기본값
    value [[value]] undefined
    get [[Get]] undefined
    set [[Set]] undefined
    writabel [[Writable]] false
    enumerable [[Enumerable]] false
    configurabel [[Configurable]] false
  5. 객체 변경 방지
    1. 객체 확장 금지
      1. 프로퍼티 추가 금지
      2. Object.preventExtensions 메서드
    2. 객체 밀봉
      1. 읽기와 쓰기만 가능
      2. Object.seal 메서드
      3. Object.isSeal 메서드로 확인 가능
    3. 객체 동결
      1. 읽기만 가능
      2. Object.Freeze 메서드
      3. Object.isFrozen 메서드로 확인 가능
      4. 객체를 동결하더라도 중첩 객체까지 동결 불가능. (얕은 변경 방지(Shallow only)) 따라서 재귀적으로 Object.freeze를 사용하여 불변 객체를 만들 수 있다.
      function deepFreeze(target){
      	if(target && typeof target === "object" && !Object.isFrozen(target)){
      		Object.freeze(target);
      		Object.keys(target).forEach(key => deepFreeze(target[key]));
      	}
      	return target
      }