내부 슬롯과 내부 메서드는 JS 엔진의 구현 알고리즘을 설명하기 위해 ECMAScript 사양에서 사용하는 의사 프로퍼티와 의사 메서드로, 이중 대괄호([[..]]
)로 감싼 이름들이 여기에 해당한다.
내부 슬롯과 메서드는 개발자가 직접 접근할 수는 없지만, 모든 객체가 가지고 있는 [[Prototype]]
내부 슬롯의 경우, 예외적으로 __proto__
를 통해 간접적으로 접근할 수 있다.
프로퍼티 생성 시 JS 엔진이 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의함
프로퍼티 어트리뷰트는 [[Value]]
, [[Writable]]
, [[Enumerable]]
, [[Configurable]]
내부 슬롯으로 이루어져 있는데, Object.getOwnPropertyDescriptor(s)
메서드를 사용하여 반환되는 프로퍼티 디스크럽터 객체를 통해 프로퍼티 어트리뷰트 정보를 간접적으로 확인할 수 있다.
프로퍼티 어트리뷰트 | 프로퍼티 디스크립터 객체의 프로퍼티 | 설명 |
---|---|---|
[[Value]] | value | 프로퍼티 키를 통해 프로퍼티 값에 접근 시 반환되는 값 |
[[Writable]] | writable | 값의 변경 가능 여부를 나타내며 false 인 경우 해당 프로퍼티는 읽기 전용 프로퍼티가 된다. |
[[Enumerable]] | eumerable | 값의 열거 가능 여부를 나타내며 false 인 경우 for...in 문이나 Object.keys 메서드 등으로 열거할 수 없다. |
[[Configurable]] | configurable | 프로퍼티 재정의 가능 여부를 나타내며 false 인 경우 프로퍼티 삭제 및 프로퍼티 어트리뷰트 값의 변경이 금지된다.단, [[Writable]] 이 true 인 경우 값 변경 및 [[Writable]] 을 false 로 변경하는 것은 허용된다. |
프로퍼티 어트리뷰트 | 프로퍼티 디스크립터 객체의 프로퍼티 | 설명 |
---|---|---|
[[Get]] | get | 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 읽을 때 호출되는 접근자 함수 |
[[Set]] | set | 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수 |
[[Enumerable]] | enumerable | 데이터 프로퍼티의 [[Enumerable]] 과 동일 |
[[Configurable]] | configurable | 데이터 프로퍼티의 [[Configurable]] 과 동일 |
const person = {
// 데이터 프로퍼티
firstName: 'mono',
lastName: 'kuma',
// 접근자 프로퍼티
get fullName() {
return `${this.firstName} ${this.lastName}`;
},
set fullName(name) {
[this.firstName, this.lastName] = name.split(' ');
}
};
// 데이터 프로퍼티를 통한 프로퍼티 값의 참조 / [[Value]]의 값이 반환
console.log(person.firstName + ' ' + person.lastName);
// 접근자 프로퍼티를 통한 프로퍼티 값의 저장 / [[Set]]의 값인 setter 함수 호출
person.fullName = 'shiro kuma';
// 접근자 프로퍼티를 통한 프로퍼티 값의 참조 / [[Get]]의 값인 getter 함수 호출
console.log(person.fullName);
// {value: 'shiro', writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(person, 'firstName'));
// {get: f, set: f, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(person, 'fullName'));
새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의 및 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의하는 것
Object.definePropert[y|ies]
메서드를 사용하며, 프로퍼티 디스크럽터 객체에서 생략된 어트리뷰트는 undefined
(value
, get
, set
의 경우) 또는 false
(writable
, enumerable
, configurable
) 기본값이 적용된다.
Object.preventExtensions
프로퍼티 동적 추가 및 Object.defineProperty
를 통한 프로퍼티 추가가 금지됨 -> Object.isExtensible
로 확장 가능한 객체인지 여부 확인 가능
Object.seal
프로퍼티 추가 및 삭제, 프로퍼티 어트리뷰트 수정이 금지됨, 즉 읽기 및 쓰기(값 갱신)만 가능 -> Object.isSealed
로 밀봉된 객체인지 여부 확인 가능
Object.freeze
프로퍼티 값 갱신도 불가능하며, 오로지 읽기만 가능 -> Object.isFrozen
으로 동결된 객체인지 여부 확인 가능
불변 객체
지금까지 살펴본 변경 메서드는 중첩 객체까지 영향을 주지 못함 -> 불변 객체를 만들기 위해서는 객체를 값으로 갖는 모든 프로퍼티에 대해 재귀적으로Object.freeze
메서드를 호출해야 함