얼레벌레
모던자바스크립트 Deep Dive - 16장 프로퍼티 어트리뷰트 본문
자바스크립트에는 개발자가 직접적으로 접근하지 못하는, 엔진의 내부 조직인 내부 슬롯과 내부 메서드가 존재함
- 내부 슬롯과 내부 메서드는 이중 대괄호([[...]])로 감싸져 있는 것들에 해당함
- 간접적으로 일부는 접근 가능 (ex) [[prototype]] → __proto__로 접근 가능
프로퍼티 어트리뷰트
* js엔진은 프로퍼티 생성 시 프로퍼티 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의
✔️ 프러퍼티 상태 - 프로퍼티 값([[Value]]), 값의 갱신 가능 여부([[Writable]]), 열거 가능 여부([[Enumerable]]), 재정의 가능 여부([[Configurable]])
⇨ Object.getOwnPropertyDescriptor(s)() : 프로퍼티 어트리뷰트를 간접적으로 확인하는 메서드로 프로퍼티 디스크립터 객체를 반환함
const person = {
name:'ny',
age:23,
}
console.log(Object.getOwnPropertyDescriptor(person,'name')) //{value: 'ny', writable: true, enumerable: true, configurable: true}
// Object.getOwnPropertyDescriptors 메서드로 모든 프로퍼티의 프로퍼티 디스크립터 객체 반환 가능
console.log(Object.getOwnPropertyDescriptors(person))
/*{
"name": {
"value": "ny",
"writable": true,
"enumerable": true,
"configurable": true
},
"age": {
"value": 23,
"writable": true,
"enumerable": true,
"configurable": true
}
}
*/
프로퍼티는 데이터 프로퍼티와 접근자 프로퍼티로 구분 가능
데이터 프로퍼티
접근자 프로퍼티
프로퍼티 정의
⇨ 새로운 프로퍼티를 추가하며 프로퍼티 어트리뷰트는 명시적으로 정의하거나 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의하는 것
✔️ Object.defineProperty() : 프로퍼티 어트리뷰트 정의
🔻 디스크립터 객체 누락시 undefined/false로 정의된다 → value, set, get은 undefined로 writable, enumerable, configurable은 false로 지정됨
const person={};
Object.defineProperty(person, 'firstName', {
value: 'Kim',
writable: true,
enumerable: true
})
console.log(person) // {firstName: 'Kim'}
// Object.defineProperties 메서드로 한번에 여러개의 프로퍼티 정의
const person={};
Object.defineProperties(person,{
'firstName':{
value: 'Kim',
writable:true,
enumerable:true,
configurable:false
},
'lastName':{
value:'ny'
}})
console.log(person) // {firstName: 'Kim', lastName: 'ny'}
// 디스크립터 객체 누락시 undefined나 false(기본값)으로 지정된다
console.log(Object.getOwnPropertyDescriptor(person,'lastName'))
// {value: 'ny', writable: false, enumerable: false, configurable: false}
// value외에 지정하지 않은 어트리뷰트들은 false 기본값으로 정의됨
객체 변경 방지
🔸 얕은 변경 방지
- 얕은 변경 방지인 객체 확장금지, 객체 밀봉, 객체 동결은 직속 프로퍼티만 변경을 방지하고 중첩 객체는 영향을 미치지 못한다.
▪️ 객체 확장 금지 : 프로퍼티 추가 불가 ✅ Object.preventExtensions() : 객체 확장 금지 / isExtensible() : 확장 가능 여부 확인
const person={name:'ny'};
console.log(person) // {name: 'ny'}
console.log(Object.isExtensible(person)) // true
Object.preventExtensions(person)
console.log(Object.isExtensible(person)) // false => 객체 확장 금지됨
// 객체 확장 금지로 프로퍼티 추가 금지 => 에러없이 무시됨
person.age=23;
console.log(person) // {name: 'ny'}
// 프로퍼티 정의에 의한 프로퍼티 추가도 금지
Object.defineProperty(person,'age',{value:23}) // Uncaught TypeError 발생
▪️ 객체 밀봉 : 프로퍼티 추가, 삭제, 재정의 불가. 즉, 읽기와 쓰기만 가능 ✅ Object.seal() : 객체 밀봉 / isSealed() : 밀봉 여부 확인
const person={name:'ny',
age:23,
}
console.log(person) // {name: 'ny', age: 23}
console.log(Object.isSealed(person)) // false
Object.seal(person) // 객체 밀봉
console.log(Object.isSealed(person)) // true
// 프로퍼티 추가, 삭제, 어트리뷰트 재정의 불가 (기존값 갱신은 가능)
// 에러없이 무시됨
person.job='student'
console.log(person) // {name: 'ny', age: 23}
delete person.name;
console.log(person) // {name: 'ny', age: 23}
▪️ 객체 동결 : 프로퍼티 추가, 삭제, 재정의, 쓰기 불가. 즉, 읽기만 가능 ✅ Object.freeze() : 객체 동결 / isFrozen() : 동결 여부 확인
const person={name:'ny',
age:23,
}
console.log(person) // {name: 'ny', age: 23}
console.log(Object.isFrozen(person)) // false
Object.freeze(person) // 객체 동결
console.log(Object.isFrozen(person)) // true
// 프로퍼티 추가, 삭제, 어트리뷰트 재정의, 값갱신 금지(읽기만 가능)
// 에러없이 무시됨
person.name='jh'
console.log(person.name) // 'ny'
🔸 불변 객체
❗️ 얕은 객체 변경 방지는 중첩 객체까지 동결을 하지 못한다. 따라서 이 경우 모든 프로퍼티에 재귀적으로 얕은 변경 방지 메서드를 호출해야 함
const person={name:'ny',
age:23,
address:{city:'seoul',district:'gangnam'},
}
Object.freeze(person)
Object.isFrozen(person) // true
Object.isFrozen(person.name) // true
Object.isFrozen(person.address) // false => 중첩 객체까지 동결 X
person.address.city = 'incheon'
console.log(person.address.city) // 'incheon'
// 재귀적으로 Object.freeze 메서드 호출
function deepFreeze(target){
if (target && typeof target == 'object' && !Object.isFrozen(target)) {
Object.freeze(target);
Object.keys(target).forEach(key => deepFreeze(target[key]));
}
return target;
}
const person={name:'ny',
age:23,
address:{city:'seoul',district:'gangnam'},
}
deepFreeze(person)
Object.isFrozen(person) // true
Object.isFrozen(person.address) // true
person.address.city = 'incheon'
console.log(person.address.city) // 'seoul' => 중첩 객체까지 동결됨
'JavaScript > 모던자바스크립트 Deep Dive' 카테고리의 다른 글
모던자바스크립트 Deep Dive - 20장 strict mode (0) | 2022.04.09 |
---|---|
모던자바스크립트 Deep Dive - 17장 생성자 함수에 의한 객체 생성 (0) | 2022.04.05 |
모던자바스크립트 Deep Dive - 15장 let, const 키워드와 블록 레벨 스코프 (0) | 2022.03.26 |
모던자바스크립트 Deep Dive - 14장 전역 변수의 문제점 (0) | 2022.03.25 |
모던자바스크립트 Deep Dive - 13장 스코프 (0) | 2022.03.25 |