16장 - 프로퍼티 어트리뷰트

hyewon ji·2023년 6월 18일

1. 내부 슬롯과 내부 메서드란

내부 슬롯과 내부 메서드는 자바스크립트 엔진의 구현 알고리즘을 설명하기 위해 ECMAScript 사양에서 사용하는 의사 프로퍼티와 의사 메서드이다. ECMAScript 사양에 이중 대괄호([[...]])로 감싼 이름들이 내부 슬롯과 내부 메서드이다.

내부 슬롯과 내부 메서드는 개발자가 직접 접근하도록 외부로 공개된 객체의 프로퍼티는 아니다. 단, 일부 내부 슬롯과 내부 메서드에 한해 간접적으로 접근할 수 있는 수단을 제공한다.

예를들어, 모든 객체는 [[Proptotype]]이라는 내부 슬롯을 갖는데 __proto__를 통해 간접적으로 접근 가능하다.

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

자바스크립트 엔진은 프로퍼티를 생성할때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의한다.

프로퍼티 상태
1. 프로퍼티 값 : value
2. 값의 갱신 가능 여부 : writable
3. 열거 가능 여부 : enumerable
4. 재정의 가능 여부 : configurable

어트리뷰트
1. [[Value]]
2. [[Writable]]
3. [[Enumerable]]
4. [[Configurable]]

어트리뷰트는 직접 접근할 수 없어 Object.getOwnPropertyDescription메서드를 사용해 간접 확인 할수 있다. 호출시 첫번째 parameter에는 객체의 참조, 두번째 parameter에는 프로퍼티 키를 전달한다. 이때, 프로퍼티 디스크립터 객체가 반환된다. 만약 존재하지 않는 프로퍼티나 상속받은 프로퍼티에 대한 프로퍼 디스크립터를 요구하면 undefined가 반환된다.

ES8에서 도입된 Object.getOwnPropertyDescription는 모든 프로퍼티의 프로퍼티 어트리뷰트를 반환한다.

const person = {
  name: 'Lee'
};

console.log(Object.getOwnPropertyDescription(person, 'name'));
// { value: 'Lee', writable: true, enumerable: true, configurable: true }

// 프로퍼티 동적 생성
person.age = 20;

console.log(Object.getOwnPropertyDescriptions(person));
/*
{
	name: { value: 'Lee', writable: true, enumerable: true, configurable: true }
    age: { value: 20, writable: true, enumerable: true, configurable: true }
}
*/

3. 데이터 프로퍼티와 접근자 프로퍼티

프로퍼티는 데이터 프로퍼티와 접근자 프로퍼티로 구분된다.

  • 데이터 프로퍼티data property : 키와 값을 구성된 프로퍼티 (함수객체의 prototype)
  • 접근자 프로퍼티accessor property : 자체적으로 값을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할때 호출되는 접근자 함수로 구성된 프로퍼티이다.(일반객체의 __proto__)

3-1. 데이터 프로퍼티

데이터 프로퍼티가 생성될때 자바스크립트 엔진이 자동으로 프로퍼티 어트리뷰트를 정의한다.

  1. [[Value]] - value
    • 프로퍼티 키를 통해 프로퍼티 값에 접근하면 반환되는 값이다.
    • 프로퍼티 키를 통해 프로퍼티 값을 변경하면 [[Value]]에 값을 재할당한다. 이때 프로퍼티가 없으면 프로퍼티를 동적 생성하고 생성한 프로퍼티의 [[Value]]에 값을 전달한다.
  2. [[Writable]] - writable
    • 프로퍼티 값의 변경 가능 여부를 나타낸다. Boolean 값
    • false일 경우, 값을 변경할수 없는 읽기 전용 프로퍼티이다.
  3. [[Enumerable]] - enumerable
    • 프로퍼티 열거 가능 여부를 나타낸다. Boolean 값
    • false일 경우, for ... inObject.keys 등의 메서드로 열거하지 못한다.
  4. [[Configurable]] - configurable
    • 프로퍼티 재정의 가능 여부를 나타낸다. Boolean 값
    • fale일 경우, 프로퍼티의 삭제 및 프로퍼티 어트리뷰트 변경이 금지된다. 단, [[Writable]]이 true인 경우 [[Value]]의 변경과, [[Writable]]을 false로 변경하는것은 어용된다.

3-2. 접근자 프로퍼티 (어트리뷰트 - 디스크립터 객체의 프로퍼티)

  1. [[get]] - get
    • 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 읽을때 호출되는 접근자 함수.
    • 접근자 프로퍼티 키로 프로퍼티 값에 접근하면 [[get]]의 값인 getter함수가 호출되고 결과가 프로퍼티 값으로 반환된다.
    • 예제
    const person = {
    	firstName: 'Gildong',
        lastName: 'Hong'
        get fullName() {
          return `${this.firstName} ${this.lastName}`;
    };
  2. [[set]] - set
    • 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수.
    • 접근자 프로퍼티 키로 프로퍼티 값에 접근하면 [[set]]의 값인 setter함수가 호출되고 결과가 프로퍼티 값으로 저장된다.
    • 예제
    const person = {
    	firstName: 'Gildong',
        lastName: 'Hong'
        set fullName(name) {
          [this.firstName, this.lastName] = name.split(' ');`
    };
  3. [[Enumerable]] - enumerable
    • 데이터 프로퍼티와 동일
  4. [[Configurable]] - configurable
    • 데이터 프로퍼티와 동일

4. 프로퍼티 정의

Object.defineProperty 메서드를 사용하면 프로퍼티의 어트리뷰트를 정의할 수 있으며, 프로퍼티 디스크립터 객체의 프로퍼티를 정의 할 수 있다..

const person = {};

Object.defineProperty(person, 'firstName', {
	value: 'gildong',
  	writable: true,
  	enumerable: true,
  	configurable: true
})

만약, 프로퍼티 디스크립터 객체의 프로퍼티를 일부 생략한다면, 해당하는 어트리뷰트에 기본값이 적용된다.

  1. 프로퍼티 디스크립터 객체의 프로퍼티 : 대응하는 프로퍼티 어트리뷰트 : 기본값
  2. value : [[Value]] : undefined
  3. get : [[Get]] : undefined
  4. set : [[Set]] : undefined
  5. writable: [[Writable]] : false
  6. enumerable : [[enumerable]] : false
  7. configurable : [[configurable]] : false

5. 객체 변경 방지

자바스크립트는 객체 변경 방지를 위한 메서드를 제공한다.
1. Object.preventExtensions

  • 프로퍼티 추가 불가
  • 프로퍼티 삭제 가능
  • 프로퍼티 값 읽기 가능
  • 프로퍼티 값 쓰기 가능
  • 프로퍼티 어트리뷰트 재정이 가능
  1. Object.seal
  • 프로퍼티 추가 불가
  • 프로퍼티 삭제 불가
  • 프로퍼티 값 읽기 가능
  • 프로퍼티 값 쓰기 가능
  • 프로퍼티 어트리뷰트 재정이 불가
  1. Object.freeze
  • 프로퍼티 추가 불가
  • 프로퍼티 삭제 불가
  • 프로퍼티 값 읽기 가능
  • 프로퍼티 값 쓰기 불가
  • 프로퍼티 어트리뷰트 재정이 불가

6. 정리

객체가 단순히 Key, Value만으로 사용되는 것이 아니라,
객체에서 제공하는 프로퍼티를 사용해 객체의 접근성과 변경 여부를 제어할 수 있다.
객체에 대한 권한이 중요시 되는 경우에 사용하면 아주 유용할 것 같다.

예를들어, 로그인시 유저의 토큰이 할당되어있는 객체는 변경 할 수 없도록
프로퍼티 디스크립터 객체의 Writable을 false로 생성하거나 Object.freeze메서드를 사용하면
보안에 안정성을 높일 수 있다는 장점이 있다.

자바스크립트에서의 객체와 프로퍼티에 대해 조금 더 알게 된것 같다!

0개의 댓글