자바스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본갑으로 자동 정의합니다.
프로퍼티 어트리뷰트로는 [[Value]], [[Writeable]], [[Enumerable]], [[Configureable]]이다.
프로퍼티 어트리뷰트에 직접 직접 접근은 할 수 없지만, Object.getOwnPropertyDescriptor 메서드를 사용하여 간접적으로 확인가능하다.
(getOwnPropertyDescriptor(arg1,arg2) 의 arg1 에 객체, arg2에 프로퍼티 키를 문자열로 전달합니다.
ES8이후로는 getOwnPropertyDescriptors(arg1) arg1에 객체 를 통해 프로퍼티 디스크립터 객체들을 반환받을 수 있습니다.
)
데이터 프로퍼티와 접근다 프로퍼티
데이터 프로퍼티 : 키 - 값 으로 구성된 일반적인 프로퍼티
접근자 프로퍼티 : 자체적으로 값을 갖지 않고, 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 호출되는 접근자 함수로 구성된 프로퍼티
프로퍼티 어트리뷰트 | 프로퍼티 디스크립터 객체의 프로퍼티 | 설명 |
---|---|---|
[[value]] | value | 프로퍼티 키를 통해 프로퍼티 값에 접근하면 반환되는 값 프로퍼티 키를 통해 프로퍼티 값을 변경하면 [[value]]에 값을 재할당한다. 이때 프로퍼티가 없으면 프로퍼티를 동적 생성하고, 생성된 프로퍼티의 [[Value]]에 값을 저장한다. |
[[Writeable]] | writeable | 프로퍼티 값의 변경 기능 여부를 나타내며 불리언 값을 갖는다. [[Writeable]]의 값이 false인 경우 해당 프로퍼티의 [[Value]]의 값을 변경할 수 없는 읽기 전용 프로퍼티가 된다. |
[[Enumerable]] | enumerable | *프로퍼티 열거 기능 여부를 나타내며, 불리언 값을 갖는다. [[Enumerable]]의 값이 false라면, 해당 프로퍼티는 for...in문이나 Object.keys등으로 열거할 수 없다. |
[[Configureable]] | configureable | *프로퍼티 재정의 가능 여부를 나타내며 불리언 값을 갖는다. false인 경우 해당 프로퍼티의 삭제, 프로퍼티 어트리뷰트 값의 변경이 금지된다. 단, [[Writeable]]이 true인 경우 [[Value]]의 변경과 [[Writeable]]의 false로의 변경은 가능하다. |
Enumberable과 Configureable은 데이터 프로퍼티와 같다.
프로퍼티 정의란 새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의하거나, 기존 프로퍼티의 어트리뷰트 재정의 하는 것을 말한다. 프로퍼티 값을 갱신 가능하도록 할지, 열거 가능하도록 할지 등을 정의하거나, 열거 가능 상태라면 열거 불가능하게 재정의 할지를 정의 할 수 있다.
Object.defineProperty 메서드를 사용하여 정의 할 수 있다. 예제를 보면 확 이해가 간다.
wrtieable을 false로 해놓으니 id가 바뀌지 않는다.
Object.defineProperty 메서드를 사용할때, 생략된 어트리뷰트에 대해서 value, get, set 은 undefined, writeable, enumerable, configureable 은 false가 기본값으로 정의된다.
Object.defineProperties 메서드를 통해서 한번에 다양한 프로퍼티를 정의할 수 있다.
객체는 변경 가능한 값이므로 재할당 없이 직접 변경 할 수 있다.
예를들어 지금 있는 예시에 user.age = 30 하면 객체에 age 프로퍼티가 추가되며 30이라는 value가 할당된다.
이러한 변경을 방지하는 메서드가 존재한다.
Object.preventExtensions()
Object.seal()
Object.freeze()
메서드 마다 객체의 변경을 금지하는 강도가 다르다. 아래로 갈 수 록 강해진다.
구분 | 메서드 | 프로퍼티 추가 | 프로퍼티 삭제 | 프로퍼티 값 읽기 | 프로퍼티 값 쓰기 | 프로퍼티 어트리뷰트 재정의 |
---|---|---|---|---|---|---|
객체 확장 금지 | Object.preventExtensions() | X | O | O | O | O |
객체 밀봉 | Object.seal() | X | X | O | O | X |
객체 동결 | Object.freeze() | X | X | O | X | X |
프로퍼티 추가를 금지한다.
프로퍼티 삭제 또한 금지된다
다 안된다고 보면된다. 읽는것만 가능하다.
근데 이 행위들이 다 얕은 변경 방지이기 때문에 중첩 객체까지 읽기 전용으로 만들기 위해선, 모든 프로퍼티에 Object.freeze()를 해줘야한다.