Javascript
[모자딥]프로퍼티 어트리뷰트 16.07 ~ 16.08
index.ys
2023. 11. 23. 22:32
프로토타입
- 어떤 객체의 상위(부모)객체의 역할을 하는 객체
- 프로토타입은 하위 객체에게 자신의 프로퍼티와 메서드를 상속한다.
- 프로퍼티와 메서드를 상속받은 하위 객체는 상위 객체의 프로퍼티와 메서드를 자유롭게 사용 가능
예제 16.07
- 일반객체 : 변수에 {}로 할당된 객체
- 함수객체 : function () {}의 객체
프로퍼티 어트리뷰트 | 프로퍼티 디스크립터 객체의 프로퍼티 |
설명 |
[[Get]] | get | 접근자 함수, getter 함수가 호출되고 결과가 프로퍼티값으로 반환됨 |
[[Set]] | set | 프로퍼티의 값을 저장할 떄 호출되는 접근자 함수 접근자 프로퍼티 키로 프로퍼티 값을 저장하면 setter 함수가 호출되고 프로퍼티 값으로 저장 |
[[Enumrable]] | enumerable | - 열거가능 여부 - false인 경우 Object.keys, for in 메서드로 열거할 수없음 |
[[Configurable]] | configurable | - 프로퍼티 재정의 가능여부 - false인 경우 프로퍼티의 삭제 변경이 금지 - [[Writable]]이 true인 경우 [[Value]]의 변경과 [[Writable]]을 false로 변경하는 것은 허용 |
- 접근자 프로퍼티와 데이터 프로퍼티를 구별하는 방법
- 접근자 프로퍼티와 데이터 프로퍼티의 Object.getOwnPropertyDescriptor 메서드가 반환한 값이다름
// 일반 객체의 __proto__는 접근자 프로퍼티다.
console.log(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__'));
// {get: ƒ, set: ƒ, enumerable: false, configurable: true}
// 함수 객체의 prototype은 데이터 프로퍼티다.
console.log(Object.getOwnPropertyDescriptor(function () { }, 'prototype'));
// {value: {...}, writable: true, enumerable: false, configurable: false}
예제 16.08
- 새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의
- 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의 할 수 있다.
- Object.defineProperty메소드를 사용하여 프로퍼티 어트립트 정의
const person = {};
// 데이터 프로퍼티 정의 => person 객체에 firstName 속성 추가 및 프로퍼티의 어트리뷰트를 정의
// Object.defineProperty 첫번쨰 인자로 객체의 참조, 데이터 프로퍼티의 키 문자열, 프로퍼티 디스크럽터 객체전달
// true나 false로 명시적으로 정의 가능
Object.defineProperty(person, 'firstName', {
value: 'Ungmo',
writable: true,
enumerable: true, //false
configurable: true //false
});
//person 객체에 'lastName' 프로퍼티키 문자열 지정, 프로퍼티 디스크립터 객체 전달
Object.defineProperty(person, 'lastName', {
value: 'Lee'
});
let descriptor = Object.getOwnPropertyDescriptor(person, 'firstName');
console.log('firstName', descriptor);
// firstName {value: "Ungmo", writable: true, enumerable: true, configurable: true}
// 디스크립터 객체의 프로퍼티를 누락시키면 undefined, false가 기본값이다.
descriptor = Object.getOwnPropertyDescriptor(person, 'lastName');
console.log('lastName', descriptor);
// lastName {value: "Lee", writable: false, enumerable: false, configurable: false}
// [[Enumerable]]의 값이 false인 경우
// 해당 프로퍼티는 for...in 문이나 Object.keys 등으로 열거할 수 없다.
// lastName 프로퍼티는 [[Enumerable]]의 값이 false이므로 열거되지 않는다.
console.log(Object.keys(person)); // ["firstName"]
// [[Writable]]의 값이 false인 경우 해당 프로퍼티의 [[Value]]의 값을 변경할 수 없다.
// lastName 프로퍼티는 [[Writable]]의 값이 false이므로 값을 변경할 수 없다.
// 이때 값을 변경하면 에러는 발생하지 않고 무시된다.
person.lastName = 'Kim';
// [[Configurable]]의 값이 false인 경우 해당 프로퍼티를 삭제할 수 없다.
// lastName 프로퍼티는 [[Configurable]]의 값이 false이므로 삭제할 수 없다.
// 이때 프로퍼티를 삭제하면 에러는 발생하지 않고 무시된다.
delete person.lastName;
// [[Configurable]]의 값이 false인 경우 해당 프로퍼티를 재정의할 수 없다.
// Object.defineProperty(person, 'lastName', { enumerable: true });
// Uncaught TypeError: Cannot redefine property: lastName
descriptor = Object.getOwnPropertyDescriptor(person, 'lastName');
console.log('lastName', descriptor);
// lastName {value: "Lee", writable: false, enumerable: false, configurable: false}
// 접근자 프로퍼티 정의
Object.defineProperty(person, 'fullName', {
// getter 함수
get() {
return `${this.firstName} ${this.lastName}`;
},
// setter 함수
set(name) {
[this.firstName, this.lastName] = name.split(' ');
},
//true를 false로 변경하기 가능
enumerable: true,
configurable: true
});
descriptor = Object.getOwnPropertyDescriptor(person, 'fullName');
console.log('fullName', descriptor);
// fullName {get: ƒ, set: ƒ, enumerable: true, configurable: true}
person.fullName = 'ys kim';
console.log(person); // {firstName: "Heegun", lastName: "Lee"}