JavaScript 객체의 프로퍼티(Property)는 값뿐만 아니라 여러 가지 속성(Attribute)을 가지고 있습니다. 이 속성들을 이해하면 객체를 더 정교하게 다루고, 의도치 않은 변경을 막거나 커스텀 엑세서(getter/setter)를 활용하는 데 큰 도움이 됩니다.
Object.getOwnPropertyDescriptor
, Object.defineProperty
API로 다룰 수 있음const obj = { foo: 123 };
console.log(Object.getOwnPropertyDescriptor(obj, 'foo'));
// {
// value: 123,
// writable: true,
// enumerable: true,
// configurable: true
// }
true
면 재할당 허용)Object.keys
)에 포함될지 여부프로퍼티 디스크립터는 크게 두 종류로 나뉩니다.
구분 | 데이터 디스크립터 | 액세서 디스크립터 |
---|---|---|
주요 속성 | value, writable | get, set |
읽기 방식 | 실제 저장된 값을 반환 | getter 함수를 실행한 결과 반환 |
쓰기 방식 | 재할당 (= ) 시 value 변경 | setter 함수를 호출 |
함께 사용할 수 없는 속성 | get, set | value, writable |
const user = {};
Object.defineProperty(user, 'name', {
value: 'Alice',
writable: false, // 재할당 금지
enumerable: true, // for...in, Object.keys에 나타남
configurable: false // 삭제 및 어트리뷰트 변경 금지
});
console.log(user.name); // Alice
user.name = 'Bob';
console.log(user.name); // 여전히 Alice
delete user.name; // 실패 (configurable: false)
const counter = { _count: 0 };
Object.defineProperty(counter, 'count', {
get() {
console.log('get 호출!');
return this._count;
},
set(val) {
console.log('set 호출!', val);
this._count = val;
},
enumerable: true,
configurable: true,
});
console.log(counter.count); // get 호출! → 0
counter.count = 5; // set 호출! 5
console.log(counter.count); // get 호출! → 5
Object.defineProperty(obj, prop, descriptor)
→ 단일 프로퍼티를 정의하거나 수정
Object.defineProperties(obj, descriptors)
→ 여러 프로퍼티를 한 번에 정의
const obj = {};
Object.defineProperties(obj, {
a: { value: 1, writable: true, enumerable: true, configurable: true },
b: {
get() { return this.a * 2; },
enumerable: true,
configurable: true
}
});
ES6부터 추가된 Reflect.defineProperty
, Reflect.getOwnPropertyDescriptor
등은 Object
API와 동작은 동일하지만, 실패 시 예외가 아닌 false
를 반환합니다.
const o = {};
const success = Reflect.defineProperty(o, 'foo', {
value: 99,
writable: false,
enumerable: false,
configurable: false
});
console.log(success); // true
console.log(Reflect.getOwnPropertyDescriptor(o, 'foo'));
Immutable 객체
writable: false
, configurable: false
로 설정해 변경을 방지라이브러리 내부 구현
가상 프로퍼티(Virtual Property)
Enum-like 상수
enumerable: false
로 숨기고, configurable: false
로 삭제 방지defineProperty
로 만든 프로퍼티는 기본 어트리뷰트가 모두 false
이므로, value만 지정하면 나머지는 모두 비활성화된 상태입니다.this.prop = value
로 선언한 프로퍼티는 기본적으로 모두 true
로 설정됩니다.obj.prop = …
)보다 defineProperty
호출이 조금 느릴 수 있으므로, 반복적으로 정의할 경우 주의하세요.