<aside> 🤚
→ 내부 슬롯과 내부 메서드의 개념에 대해 알아보자
const o = {};
// 내부 슬롯은 자바스크립트 엔진의 내부 로직이므로 직접 접근할 수 없다.
o.[[Prototype]] // -> Uncaught SyntaxError: Unexpected token '['
// 단, 일부 내부 슬롯과 내부 메서드에 한하여 간접적으로 접근할 수 있는 수단
o.__proto__ // -> Object.prototype
const obj = { a: 1 };
console.log(obj.a); // 1 (우리가 직접 쓸 수 있는 프로퍼티)
console.log(obj.__proto__); // object의 프로토타입(사실은 내부 슬롯 [[Prototype]]을 간접으로 본 것)
// 직접 [[Prototype]]을 꺼낼 순 없다!
// console.log(obj.[[Prototype]]); // SyntaxError!!
</aside>
<aside> ✂️
→ 프로퍼티 어트리뷰트란?
→ 프로퍼티 디스크립터 객체 ?
→ Object.getOwnPropertyDescritor
const person = {
name: 'Lee'
};
// 메서드 호출 방법
// Object.getOwnPropertyDescriptor(obj, key)
// 하나의 프로퍼티에 대해 프로퍼티 디스크립터 객체를 반환한다.
console.log(Object.getOwnPropertyDescriptor(person, 'name'));
// {value: "Lee", writable: true, enumerable: true, configurable: true}
→ Object.getOwnPropertyDescritors
const person = {
name: 'Lee'
};
// 프로퍼티 동적 생성
person.age = 20;
// 모든 프로퍼티의 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터
console.log(Object.getOwnPropertyDescritors(person));
/*
name: {value: "Lee", writable: true, enumerable: true, configurable: true},
age: {value: 20, writable: true, enumerable: true, cnofigurable: true}
*/
</aside>
<aside> 💽
→ 프로퍼티는 데이터 프로퍼티와 접근자 프로퍼티로 구분할 수 있다.
<aside> 👨💻
→ 데이터 프로퍼티 어트리뷰트는 자바스크립트 엔진이 프로퍼티를 생성할 때 기본값으로 정의
| 프로퍼티
어트리뷰트 | 프로퍼티 디스크립터
객체의 프로퍼티 | 설명 |
| --- | --- | --- |
| [[Value]] | value | 1. 프로퍼티 키를 통해 프로퍼티 값에 접근하면 반환되는 값
2. 프로퍼티 키를 통해 값을 변경 시 [[Value]] 값을 재할당
3. 프로퍼티가 없으면 프로퍼티 동적 생성 후 [[Value]] 값 저장 |
| [[Writable]] | writable | 1. 프로퍼티 값의 변경 여부를 나타내며, 불리언 값
2. [[Writable]] 값이 false 인 경우 프로퍼티의 [[Value]]의 값은 변경할 수 없는 읽기 전용 프로퍼티로 변경 |
| [[Enumerable]] | enumerable | 1. 프로퍼티의 열거 가능 여부를 나타내며, 불리언 값
2. [[Enumerable]] 값이 false 인 경우 프로퍼티는 for…in
또는 Object.keys
로 열겨 불가능 |
| [[Configurable]] | configurable | 1. 프로퍼티의 재정의 가능 여부를 나타내며, 불리언 값
2. [[Configurable]] 값이 false 인 경우 해당 프로퍼티의 삭제, 프로퍼티 값의 변경이 금지된다.
3. 단 [[Writable]]이 true 인 경우 [[Value]]의 변경과 [[Writable]]을 false로 변경하는 것은 허용된다. |
→ 예제 살펴보기
const name = {
name: 'Lee'
};
// 프로퍼티 동적 생성
person.age = 20;
console.log(Object.getOwnPropertyDescriptors(person));
/*
name: {value: "Lee", writable: true, enumerable: true, configurable: true},
age: {value: 20, writable: true, enumerable: true, cnofigurable: true}
*/
</aside>
<aside> 👩💻
→ 접근자 프로퍼티란?
| 프로퍼티 어트리뷰트 | 프로퍼티 디스크립터 객체의 프로퍼티 | 설명 | | --- | --- | --- | | [[Get]] | get | 1. 접근자 프로퍼티를 통해 데이터 프로퍼티 값을 읽을 때 호출되는 접근자 함수 2. 접근자 프로퍼티 키로 프로퍼티 값에 접근하면 [[Get]]의 값, getter 함수가 호출되고, 결과가 프로퍼티 값으로 반환 | | [[Set]] | set | 1. 접근자 프로퍼티를 통해 프로퍼티의 값을 저장할 때 호출되는 접근자 함수 2. 접근자 프로퍼티 키로 프로퍼티 값을 저장하면 [[Set]]의 값, setter 함수가 호출되고, 결과가 프로퍼티 값으로 저장 | | [[Enumerable]] | enumerable | 데이터 프로퍼티의 [[Enumerable]]과 같다 | | [[Configurable]] | configurable | 데이터 프로퍼티의 [[Configurable]]과 같다 |
→ 접근자 함수는 getter/setter 함수라고도 부른다.
const person = {
// 데이터 프로퍼티
firstName: 'Ungmo',
lastName: 'Lee',
// fullName은 접근자 함수로 구성된 접근자 프로퍼티다.
// getter 함수
get fullName() {
return `${this.firstName} ${this.lastName}`;
},
//setter 함수
set fullName(name) {
// 배열 디스트럭처링 할당: "31.1 배열 디스트럭처링 할당" 참고
[this.firstName, this.lastName] = name.split(' ');
}
};
// 데이터 프로퍼티를 통한 프로퍼티 값의 참조.
console.log(person.firstName + ' ' + person.lastName); // Ungmo Lee
// 접근자 프로퍼티를 통한 프로퍼티 값의 저장
// 접근자 프로퍼티 fullName에 값을 저장하면 setter 함수가 호출된다.
person.fullName = 'Heegun Lee';
console.log(person); // {firstName: "Heegun", lastName: "Lee"}
// 접근자 프로퍼티를 통한 프로퍼티 값의 참조
// 접근자 프로퍼티 fullName에 접근하면 getter 함수가 호출된다.
console.log(person.fullName); // Heegun Lee
// firstName은 데이터 프로퍼티다.
// 데이터 프로퍼티의
// 어트리뷰트 [[Value]], [[Writable]] [[Enumerable]], [[Configurable]]
let descriptor = Object.getOwnPropertyDescriptor(person, 'firstName');
console.log(descriptor);
// {value: "Heegun", writable: true, enumerable: true, configurable: true}
// fullName은 접근자 프로퍼티다.
// 접근자 프로퍼티의
// 어트리뷰트 [[Get]], [[Set]] [[Enumerable]], [[Configurable]]
descriptor = Object.getOwnPropertyDescriptor(person, 'fullName');
console.log(descriptor);
// {get: f, set: f, enumerable: true, configurable: true}
→ 정리하기
→ 내부 슬롯/메서드로 접근자 프로퍼티 fullName 동작
→ 접근자 프로퍼티와 데이터 프로퍼티를 구별하는 방법
// 일반 객체의 __proto__는 접근자 프로퍼티다.
Object.getOwnPropertyDescriptor(Object.prototype, '__proto__');
// {get: f, set: f, enumerable: false, configurable: true}
// 함수 객체의 prototype은 데이터 프로퍼티다.
Object.getOwnPropertyDescriptor(function(){}, 'prototype');
// {value: {...}, writable: true, enumerable: false, configurable: false}
→ 정리하기
→ 그래서 이거 왜 알아야함..?
</aside>
<aside> 🦸
</aside>
<aside> 🗣️
</aside>
<aside> 🔒
</aside>
<aside> 🤐
</aside>
<aside> 🧊
</aside>