ECMAScript 사양에 등장하는 이중 대괄호
[[...]]
로 감싼 이름을 내부슬롯과 내부 메서드이다.
간접적으로 접근 할 수 있다.
__porto__
를 통해 간접적으로 접근이 가능하다.cosnt o ={};
//내부 슬롯은 자바스크립트 엔진의 내부 로직이므로 직접 접근 할 수 없다.
o.[[Prototype]] //Error
//단, 일부 내부 슬롯과 내부 메서드 한에서 간접적으로 접슨 하룻 있는 수단이 제공된다.
o__propety__ //-> Object.prototype
- 프로퍼티 어트리뷰트
자바스크립트 엔진이 관리하는 내부 상태 값인 내부슬롯[[value]]
[[Writable]]
[[Enumerable]]
[[Configurable]]
Object.getOwnPropertyDescriptor
메서드를 통해 간접적으로 확일 할 수 있다.
- 프로퍼티 디스크립터 객체
Object.getOwnPropertyDescriptor
메서드를 통해 프로퍼티 어트리뷰트 의 정보를 반환되어 나오는 객체
undefined
가 반환된다.Object.getOwnPropertyDescriptor
는 모든 프로퍼티의 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체를 반환한다.const person={
name : 'Lee'
};
//프로퍼티 동적 생성
person.age = 20;
//모든 프로퍼티의 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체들을 반환한다.
console.log(Object.propertyDescriptors(person));
/*
{
name : {value : 'Lee', writable : true, enumerable : true, configurable : true},
age : {value : 20, writable : true, enumerable : true, configurable : true},
*/
- 데이터 프로퍼티 (data property)
키와 값으로 구성된 일반적인 프로퍼티
[[Value]]
[[Writable]]
불리언 값
을 갖는다.false
인 경우, 해당 프로퍼티 [[Value]]의 값을 변경할 수 없는 읽기 전용 프로퍼티
가 된다.[[Enumerable]]
불리언 값
을 갖는다.false
인 경우 해당 프로퍼티는 for..in문
이나 Object.keys
메서드 등으로 열거 할 수 없다.[[Configurable]]
불리언 값
을 갖는다.false
인 경우 해당 프로퍼티의 삭제
,어트리뷰트 값의 변경
이 금지 된다.
- 접근자 프로퍼티 (accessor property)
자체적으로 값을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 호출되는 접근자 함수로 구성된 프로퍼티
[[Get]]
데이터 프로퍼티의 값을 읽을 때
호출되는 접근자 함수값에 접근
하면 프로퍼티 어트리뷰트 [[Get]]의 값, 즉 getter 함수
가 호출되고 그 결과가 프로퍼티 값을 반환한다.return
이 꼭 있어야 한다.[[Set]]
데이터 프로퍼티의 값을 지정할 때
호출되는 접근자 함수값을 저장
하면 프로퍼티 어트리뷰트 [[Set]]의 값, 즉 setter 함수
가 호출되고 그 결과 프로퍼티 값으로 저장된다.[Enumerable]]
데이터 프로퍼티와 동일하다.
[[Configurable]]
데이터 프로퍼티와 동일하다.
const person = {
//데이터 프로퍼티
firstName = 'Ungmo',
lastName = 'Lee',
//접근자 프로퍼티
//getter함수
get fullName(){
return `${this.firstName} ${this.lastName}`;
},
//setter함수
set fullName(){
[this.firstName, this.lastName] = name.split(' ');
}
};
데이터 프로퍼티
를 통한 프로퍼티 값 참조
consoel.log(person.firstName + ' ' + person.lastName);
//Ungmo Lee
접근자 프로퍼티
를 통한 프로퍼티 값의 저장
person.fullName = 'Heegun Lee';
console.log(person);
//{firstName : 'Heegun', lastName : 'Lee'}
접근자 프로퍼티
를 통한 프로퍼티 값의 참조
getter 함수
가 호출된다.console.log(person.fullName);
//Heegun Lee
접근자 프로퍼티
의 어트리뷰트 출력[[Get]]
[[Set]]
[[Enumerable]]
[[Configurable]]
을 가지고 있다.let descriptor = Object.getOwnPropertyDescriptor(person, 'fullName');
console.log(descriptor);
//{get : f, set : f, enumerable : true, configurable : true}
어떤 객체의 상위(부모) 객체의 역활을 하는 객체
- 하위(자식)객체에게 자신의 프로퍼티와 메서드를 상속한다.
- 상속 받은 하위 객체는 자신의 프로퍼티 또는 메서드의 것처럼 자유롭게 사용할 수 있다.
프로토타입 체인
은 프로토타입이 단반향 링크드 리스트 형태로 연결되어 있는 상속 구조이다.
+ 객체의 프로퍼티나 메서드에 접근하려고 할때 해당 객체에 접근하려는 프로퍼티 또는 메서드가 없다면 프로토타입 체인을 따라 프로토타입의 프로토타입의 프로퍼티나 메서드를 차례로 검색한다.
- 새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의
- 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의하는 것 →
Object.defineProperty
와Object.definePropertes
메서드 사용
Object.defineProperty
: 한번에 하나의 프로퍼티만 정의
Object.definePropertes
: 여러개의 프로퍼티를 한 번에 정의
const person ={};
//데이터 프로퍼티 정의
Object.defineProperty(person.'firstName',{
value : 'Ungmo',
writable : true,
enumerable : true,
configurable : true
});
Object.defineProperty(person. 'lastName', {
vaule: 'Lee'
});
//접근자 프로퍼티 정의
Object.defineProperty(person, 'fullName',{
get(){
return `${this.firstName}, ${this.lastName}`;
},
set(name){
[this.firstName, this.lastName] = name.split(' ');
},
enumerable : true,
configurable : true
});
[[writable]]
[[enumerable]]
[[configurable]]
생략 가능value
, get
, set
: undefinedwirtable
, enumerable
, configurable
: falseObject.preventExtension 메서드
- 프로퍼티 추가 금지 (동적 추가, Object.defineProperty메서드)
Object.isExtension 메서드
로 확장 가능한 객체인지 확인 할 수 있다.
const person = {name : 'Lee'};
//person 객체는 확장이 금지된 객체가 아니다.
console.log(Object.isExtension(person)); //true
//person 객체의 확장을 금지하여 프로퍼티 추가를 금지한다.
Object.preventExtension(person);
//person 객체는 확장이 금지된 객체이다.
console.log(Object.isExtension(person)); //false
person.age = 20; //무시. strict mode에서는 에러 console.log(person); //{name : 'Lee'}
delete.person.name; console.log(person); //{}
Object.defineProperty(person, 'age',{value : 20}); //TypeError : Cannnot define property age, object is not extensible
Object.seal 메서드
밀봉된 객체는 읽기와 쓰기만 가능하다.
- 추가, 삭제, 재 정의를 금지
Object.isSealed 메서드
로 밀봉 객체 여부 확인 가능
const person = {name : 'Lee'};
//person 객체는 밀봉된 객체가 아니다.
console.log(Object.isSealed(person)); //false
//person 객체의 밀봉하여 프로퍼티 추가, 삭제, 재정의를 금지한다.
Object.Seal(person);
//person 객체는 밀봉된 객체이다.
console.log(Object.isSealed(person)); //true
//밀봉된 객체는 congiurable이 false이다.
console.log(Object.getOwnPropertyDescriptor(person));
/*
{
name : {value : 'Lee', wirtable : true, enumerable : true, configurable : false,}
*/
person.age = 20; //무시. strict mode에서는 에러 console.log(person); //{name : "Lee"}
delete.person.name; //무시. strict mode에서는 에러 console.log(person); //{name : 'Lee'}
person.name = 'Kiem'; console.log(person); //{name : 'Kim'}
Object.defineProperty(person, 'name',{configurable : true}); //TypeError : Cannnot redefine propery : name
Object.freeze 메서드
동결된 객체는 읽기만 가능하다.
- 프로퍼티 추가, 삭제, 재정의, 쓰기 금지
Object.isFrozen 메서드
동결 객체인지 여부 확인 가능
const person = {name : 'Lee'};
//person 객체는 동결된 객체가 아니다.
console.log(Object.isFrozne(person)); //false
//person 객체의 동결하여 프로퍼티 추가, 삭제, 재정의, 쓰기가 금지한다.
Object.Freeze(person);
//person 객체는 동결된 객체이다.
console.log(Object.isFrozne(person)); //true
//밀봉된 객체는 Writable이 false이다.
console.log(Object.getOwnPropertyDescriptor(person));
/*
{
name : {value : 'Lee', wirtable : false, enumerable : true, configurable : false,}
*/
프로퍼티 추가가 금지된다.
person.age = 20; //무시. strict mode에서는 에러 console.log(person); //{name : "Lee"}
프로퍼티 삭제가 금지된다.
delete.person.name; //무시. strict mode에서는 에러 console.log(person); //{name : 'Lee'}
프로퍼티 값 갱신이 금지된다.
person.name = 'Kim'; //무시, strict mode에서 에러 console.log(person); //{name : 'Lee'}
프로퍼티 어트리뷰트 재정의가 금지된다.
Object.defineProperty(person, 'name',{configurable : true}); //TypeError : Cannnot redefine propery : name'
객체 확장 금지
객체 밀봉
객체 동결
은 얕은 변경 방식으로 중첩 객체까지 동결 할 수 었다.
따라서,재귀적으로 Object.freeze 메서드
를 호출해야 한다.
fucntion 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 : 'Lee',
address : {city : 'Seoul'}
};
//깊은 객체 동결
deepFreeze(person);
console.log(Object.isFrozen(person)); //true
console.log(Objdec.isFrozen(person.address)); //true
person.address.city = 'Busan';
console.log(person.address);
//city : 'Seoul'
이론을 공부하는 느낌이라 핵심개념만 알고 넘어가도 될 것 같은데 언제 어떻게 이것을 사용하는지 "실무에서 어떻게 사용할까?"하는 생각을 가지며대한 의문을 가지고 공부를 해야 했다.
그리고 마지막 예제 코드가 이해하기 어려워서 찾아보니 다행히 동영상 강의가 이 부분까지 있어서 객체 동결 강의를 보며 코드를 이해할 수 있었다. 저자 강의는 이번 장까지만 업로드 되어 있어서 조금 아쉽다.