객체는 값(value) 외에도 플래그(flag)라는 특별상 속성이 있다. 플래그는 아래 3가지 종류가 있다. 일반적으로 객체를 선언하면(객체 리터럴 혹은 Object 생성자 함수 사용) 프로퍼티의 플래그는 true
를 기본값으로 가진다.
프로퍼티 값 수정 | 프로퍼티 삭제 | 반복문 나열 | 플래그 수정 | |
---|---|---|---|---|
writable: false | ❌ | ✅ | ✅ | ✅ |
enumerable: false | ✅ | ✅ | ❌ | ✅ |
configurable: false | ✅ | ❌ | ✅ | ❌ |
true
: 프로퍼티 값 수정 가능false
: 프로퍼티 값 수정 불가(프로퍼티 삭제는 가능)true
: 반복문으로 나열 가능false
: 반복문으로 나열 불가true
: 프로퍼티 삭제 / 플래그 수정 가능false
: 프로퍼티 삭제(프로퍼티 값 수정은 가능) / 플래그 수정 불가프로퍼티에 대한 정보는 Object.getOwnPropertyDescriptor
메서드를 이용해 얻을 수 있다. 이 메서드를 호출하면 프로퍼티 설명자(descriptor)라는 객체가 반환된다. 이 설명자 객체에 플래그 정보가 담겨있다.
Object.getOwnPropertyDescriptor(obj, property)
const user = { name: 'john', age: 30 }
const descriptor = Object.getOwnPropertyDescriptor(user, 'name')
console.log(descriptor)
// {value: 'john', writable: true, enumerable: true, configurable: true}
<aside> 💡 객체 리터럴, 객체 복사(Object.assign, 전개연산자)등으로 만든 객체의 모든 플래그 기본값은 true. Object.defineProperty로 프로퍼티를 추가할 때 명시하지 않은 모든 플래그 기본값은 false
</aside>
Object.defineProperty
메서드를 사용하면 객체의 플래그를 변경할 수 있다. 인자로 넘겨받은 정보를 이용해 새로운 프로퍼티를 생성해준다. 이때 플래그 정보를 명시하지 않으면 플래그 값은 자동으로 false가 된다.
Object.defineProperty(obj, property, descriptors)
const user = {};
Object.defineProperty(user, 'name', {
value: 'johan'
})
console.log(user) // {name: 'johan'}
console.log(Object.getOwnPropertyDescriptor(user, 'name'))
// {value: 'johan', writable: false, enumerable: false, configurable: false}
writable
플래그를 이용해 객체의 특정 속성의 값을 쓰지 못하도록(non-writable) 할 수 있다. 에러는 엄격 모드("use strict")에서만 발생한다.
const user = { name: 'john' };
Object.defineProperty(user, 'name', {
writable: false
})
user.name = 'smith' // Error: Cannot assign to read only property 'name'
console.log(user) // {name: 'john'}