티스토리 뷰
16.1 내부 슬롯과 내부 메서드
자바스크립트 엔진의 구현 알고리즘을 설명하기 위해 ECMAScript 사양에서 사용하는 의사 프로퍼티와 의사 메서드
- 이중 대괄호 [[...]]
- 공개된 객체의 프로퍼티는 아님: 엔진의 내부 로직이므로 직접 접근하거나 호출할 수 있는 방법을 제공하지 않음
- 간접적으로 접근 가능: 모든 객체는 [[Prototype]]이라는 내부 슬롯을 갖는데 이는 __proto__로 접근할 수 있음
16.2 프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체
자바스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의
- 프로퍼티의 값[[Value]]
- 값의 갱신 가능 여부[[Writable]]
- 열거 가능 여부[[Enumerable]]
- 재정의 가능 여부[[Configurable]]
프로퍼티 어트리뷰트에 직접 접근할 수 없지만
Object.getOwnPropertyDescriptor(객체 참조, 프로퍼티 키) 메서드로 간접적으로 확인할 수 있음
const person = {
name: 'Lee'
};
console.log(Object.getOwnPropertyDescriptor(person, 'name'));
// {value: 'Lee', writable: true, enumerable: true, configurable: true}
- 프로퍼티 디스크립터 객체 반환
- 존재하지 않거나 상속받은 프로퍼티를 전달할 경우 undefined 리턴
- ES8부터 객체만 인자로 전달할 경우 모든 프로퍼티의 프로퍼티 디스크립터 객체 반환
16.3 데이터 프로퍼티와 접근자 프로퍼티
1.데이터 프로퍼티(data property)
키와 값으로 구성된 프로퍼티
프로퍼티 어트리뷰트 | 프로퍼티 디스크립터 객체의 프로퍼티 |
기본값 | 설명 |
[[Value]] | value | 프로퍼티 값 | 프로퍼티 값 |
[[Writable]] | writable | true | boolean. 프로퍼티 value의 변경 가능 여부를 나타냄(읽기 전용 여부) false일 때 값을 변경하려 하면 에러가 발생하지 않고 무시됨 |
[[Enumerable]] | enumerable | true | boolean. (반복문 등으로) 열거 가능 여부를 나타냄 |
[[Configurable]] | configurable | true | boolean. 프로퍼티 재정의 가능 여부 false인 경우 - 해당 프로퍼티 삭제, 프로퍼티 어트리뷰트 값 변경 금지 - 예외: writable이 true인 경우 값 변경, writable false로 변경 가능 - 값을 삭제하려하면 에러가 발생하지 않고 무시됨 - 프로퍼티 어트리뷰트 값을 변경하려 하면 TypeError 발생 |
2. 접근자 프로퍼티(accessor property)
접근자 함수(자체 값을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용)로 구성된 프로퍼티
프로퍼티 어트리뷰트 | 프로퍼티 디스크립터 객체의 프로퍼티 |
설명 |
[[Get]] | get | getter 함수 데이터 프로퍼티의 값을 읽을 때 호출되는 접근자 함수 |
[[Set]] | set | setter 함수 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수 |
[[Enumerable]] | enumerable | 데이터 프로퍼티와 동일 |
[[Configurable]] | configurable | 데이터 프로퍼티와 동일 |
const person = {
firstName: 'Ungmo',
lastName: 'Lee',
get fullName() {
return `${this.firstName} ${this.lastName}`
},
set fullName(name) {
[this.firstName, this.lastName] = name.split(' ');
}
};
console.log(person.fullName); // getter 호출 Ungmo Lee
person.fullName = 'Heegun Lee'; // setter 호출
console.log(person); // {firstName: 'Heegun', lastName: 'Lee'}
console.log(person.fullName); // Heegun Lee
- [[GET]]] 동작
1. 프로퍼티 키가 유효한지 확인
2. 프로토타입 체인에서 프로퍼티 검색
3. 검색된 프로퍼티가 데이터 프로퍼티인지 접근자 프로퍼티인지 확인
4. 접근자 프로퍼티의 프로퍼티 어트리뷰트 [[GET]](getter 함수)의 값을 호출하여 반환
16.4 프로퍼티 정의
Object.defineProperty(객체, 키, 프로퍼티 디스크립터 객체)로 프로퍼티 어트리뷰트를 명시적으로 정의/재정의 가능
Object.defineProperties(객체, {키: 프로퍼티 어트리뷰트값})로 여러 프로퍼티를 한번에 정의/재정의 가능
프로퍼티 디스크립터 객체의 프로퍼티를 생락하여 정의할 경우 기본값
프로퍼티 디스크립터 객체의 프로퍼티 | 대응하는 프로퍼티 어트리뷰트 | 생략 시 기본값 |
value | [[Value]] | undefined |
get | [[Get]] | undefined |
set | [[Set]] | undefined |
writable | [[Writable]] | false |
enumerable | [[Enumerable]] | false |
configurable | [[Configurable]] | false |
16.5 객체 변경 방지
구분 | 메서드 | 프로퍼티 추가 |
프로퍼티 삭제 |
프로퍼티 값 읽기 |
프로퍼티 값 쓰기 |
프로퍼티 어트리뷰트 재정의 |
객체 확장 금지 | Object.preventExtensions Object.isExtensible |
X | O | O | O | O |
객체 밀봉 | Object.seal Object.isSealed |
X | X | O | O | X |
객체 동결 | Object.freeze Object.isFreezed |
X | X | O | X | X |
밀봉된 객체는 configuable 값 false(writable true)
동결된 객체는 configuable 값 false (writable false )
불변 객체
위 변경 방지 메스드들은 얕은 변경 방지(shallow only)로 직속 프로퍼티의 변경만 방지되고 중첩된 객체는 제어할 수 없음
> 객체의 중첩 객체까지 변경 불가능한 읽기 전용 객체를 구현하려면 객체를 값으로 갖는 모든 프로퍼티에 재귀적으로 Object.freeze를 호출해야 함
'책' 카테고리의 다른 글
[딥다이브] 18. 함수와 일급 객체 (0) | 2024.05.13 |
---|---|
[딥다이브] 17. 생성자 함수에 의한 객체 생성 (0) | 2024.05.12 |
[딥다이브] 15. let, const 키워드와 블록 레벨 스코프 (1) | 2024.04.28 |
[딥다이브] 14. 전역 변수의 문제점 (0) | 2024.04.28 |
[딥다이브] 13. 스코프 (0) | 2024.04.22 |