모던 자바스크립트 Deep Dive 16장을 읽으며 정리한다.
property attribute
- value (값)
- writable (갱신 가능 여부)
- enumerable (열거 가능 여부)
- configurable (재정의 가능 여부)
자바스크립트 엔진은 property를 생성할 때 property의 상태를 나타내는 것들을 property attribute를 기본값으로 자동 정의. 상태란 위 네 가지를 뜻함.
property attribute는 meta-property인 내부 슬롯이다. 직접 접근 불가능, 간접 접근 가능
const fruit = {
name : 'pear'
};
fruit.age = 10;
console.log(Object.getOwnPropertyDescriptors(fruit));
/*
age: {value: 10, writable: true, enumerable: true, configurable: true}
name: {value: 'pear', writable: true, enumerable: true, configurable: true}
*/
property의 분류 : data property / accessor property
- data property : 키와 값으로 구성된 것 . 여태 했던 거다!
- accessor property : 자체적으로는 값을 갖지 않는다. 다른 data proprty의 값을 읽거나 저장할 때 호출되는 accessor funtion으로 구성됨
data property의 property attribute
- value (값) : property의 값으로 초기화된다
- writable (갱신 가능 여부) : Boolean, false일 경우 값을 변경할 수 없다.
- enumerable (열거 가능 여부) : Boolean, false일 경우 for... in이나 Object.keys 등으로 열거 불가능!
- configurable (재정의 가능 여부) : Boolean, false일 경우 삭제나 값의 변경이 금지된다. 단, writable이 true 라면 value의 변경과 writable을 false로 변경이 허용된다.
accessor property의 property attribute
- get : accessor property로 값을 읽을 때 호출되는 함수다. (getter 함수) 그 결과가 프로퍼티 값으로 반환된다.
- set : accessor property로 값을 저장할 때 호출되는 함수다. (setter 함수) 그 결과가 프로퍼티 값으로 저장된다.
- enumerable (열거 가능 여부)
- configurable (재정의 가능 여부)
한번 accessor property를 살펴보자.
const fruit = {
name: "pear",
get fruitName() {
return `${this.name}`; //getter 함수
},
set fruitName(fname) {
[this.name] = fname.split(" "); //setter 함수
//배열 디스트럭처링 할당 -> 추후 공부한다
},
};
fruit.fruitName = "cherry";
console.log(fruit); // {name: 'cherry'}
console.log(fruit.fruitName); // cherry
console.log(Object.getOwnPropertyDescriptors(fruit, "name"));
// fruitName: {enumerable: true, configurable: true, get: ƒ, set: ƒ}
// name: {value: 'cherry', writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptors(fruit, "fruitName"));
// fruitName: {enumerable: true, configurable: true, get: ƒ, set: ƒ}
// name: {value: 'cherry', writable: true, enumerable: true, configurable: true}
property 정의
앞서 봤던 property attribute를 명시적으로 정의할 수 있다. 바로 Object.defineProperty 를 쓰면 된다! Object.defineProperties를 쓰면 여러 개를 정의할 수 있다.만약 discripter 객체의 property를 누락시킨다면 undefined, false가 기본값이다. value, get, set의 경우는 undefined, 나머지는 false다.
const fruit = {
};
Object.defineProperty(fruit, 'name',{
value : 'cherry'
});
console.log(Object.getOwnPropertyDescriptors(fruit))
//name: {value: 'cherry', writable: false, enumerable: false, configurable: false}
console.log(Object.keys(fruit)); // []
fruit.name = 'pear';
console.log(fruit); //{name: 'cherry'}, 변경되지 않는다.
delete fruit.name; //사라지지 않는다.
그렇다면 객체의 변경을 방지하는 방법은 무엇일까?
- Object.preventExtensions , 객체 확장 금지. 프로퍼티 추가가 금지된다.
- Object.preventExtensions() 안에 객체를 넣으면 프로퍼티 추가가 금지된다.
- Object.isExtensible()을 사용하면 확장 금지인지 알 수 있다.
- 추가는 금지되지만 삭제는 가능하다.
- Object.seal , 객체 밀봉. 프로퍼티 추가 및 삭제, property attribute 정의가 금지된다.
- 밀봉된 객체는 읽기와 쓰기만 가능하다.
- 즉, 값 갱신은 가능하다.
- 그 여부는 Object.isSealed method로 확인 가능하다.
- Object.freeze , 객체 동결. 프로퍼티 추가 및 삭제, property attribute 재정의 금지, property 값 갱신 금지.
- 동결된 객체는 읽기만 가능하다.
- Object.isFrozen 메소드로 확인 가능하다.
하지만 중첩 객체라면 어떨까? : 불변 객체
위 방법은 직속 proerty만 변경이 방지되고, 중첩 객체까지는 영향을 주기 어렵다. 중첩 객체까지 변경이 불가능하게 하려면 어떻게 해야 할까?
: 객체를 값으로 갖는 모든 property에 대해 재귀적으로 Object.freeze method를 호출해야 한다.
다음과 같은 함수를 작성할 수 있다.
function Freeze(obj){
if (obj && typeof obj === 'object' && !Object.isFrozen(obj)){
Object.freeze(obj);
Object.keys(obj).forEach(key => Freeze(obj[key]));
}
return obj
}
const fruit = {
name : 'cherry',
profile : { year : '1900'}
}
console.log(Object.isFrozen(fruit)); //false
console.log(Object.isFrozen(fruit.profile)); //false
Freeze(fruit);
console.log(Object.isFrozen(fruit)); //true
console.log(Object.isFrozen(fruit.profile)); //true
fruit.profile.year = '2000'
console.log(fruit);
// name: "cherry"
// profile: {year: '1900'}
'JavaScript' 카테고리의 다른 글
[JavaScript] Prototype(함수 객체, 리터럴 표기법, 프로토타입 객체) (0) | 2022.02.16 |
---|---|
[JavaScript] 생성자 함수에 의한 객체 생성 (0) | 2022.02.12 |
[JavaScript] var 대신 let/const를 사용하자(ES6) (0) | 2022.02.07 |
[JavaScript] Global variables (전역 변수) (0) | 2022.02.06 |
[JavaScript] Function Note (0) | 2022.02.05 |
댓글