객체 프로퍼티의 종류
객체 프로퍼티는 데이터 프로퍼티, 접근자 프로퍼티로 나뉜다.
데이터 프로퍼티(Data Property)
key:value 형태의 값에 문자열, 숫자, 함수, 객체, 배열 등등의 값이 들어간 모든 프로퍼티를 의미한다.
접근자 프로퍼티(Accessor Property)
접근자 프로퍼티는 함수이며, get과 set의 역할을 한다.
그러나, 외부에서 해당 객체를 사용할 때 접근자 프로퍼티를 일반 프로퍼티처럼 사용할 수 있다.
Getter & Setter
접근자 프로퍼티는 getter, setter 메서드로 표현될 수 있다.
그리고 객체에서 getter, setter는 각각 get, set으로 나타낼 수 있다.
getter 메서드는 객체 프로퍼티를 가져오는 함수이며,
setter 메서드는 객체 프로퍼티 값을 설정하는 함수이다.
getter 메서드는 obj.property 로 프로퍼티를 읽을 때 실행되며
setter 메서드는 obj.property = value 로 프로퍼티에 값을 할당할 때 실행된다.
const obj = {
macro:'hi',
get hello(){
return this.macro;
},
set hello(value){
this.macro = value;
}
};
console.log(obj.hello); // hi
obj.hello = 'hello';
console.log(obj.hello); // hello
다음과 같이 프로퍼티를 호출할 때 get, 프로퍼티에 값을 할당할 때 set 메서드가 실행된다.
객체 내부에서는 get, set 키워드를 사용했지만
객체 외부에서는 일반 프로퍼티처럼 obj.hello
를 사용하면 된다.
물론 getter, setter를 모두 구현할 필요는 없이 둘 중 하나만 사용할 수도 있다.
const obj = {
macro:'hi',
get hello(){
return this.macro;
},
};
console.log(obj.hello); // hi
obj.hello = 'this is not work';
console.log(obj.hello); // hi
다음과 같이 코드를 작성하면, setter가 존재하지 않기 때문에 getter에서 출력된 값이 변하지 않는다.
hello 메서드는 가상 프로퍼티로, 읽고 쓸 수 있으나 실제로 존재하는 프로퍼티는 아니다.
접근자 프로퍼티 설명자(Descriptor)
이전 글에서도 다뤘듯이,
접근자 프로퍼티에도 설명자가 존재한다.
이전 글에서 설명한 설명자는 데이터 프로퍼티의 설명자에 해당하며,
지금은 접근자 프로퍼티의 설명자에 대해 배워보자.
데이터 설명자에는 value, writable, enumerable, configurable 속성이 있으며
접근자 프로퍼티에는 get, set, enumerable, configurable 속성이 있다.
각각 설명자들의 개념은 다음과 같다.
get : 인수가 없으며, 프로퍼티를 읽을 때 동작한다.
set : 인수가 하나이며, 프로퍼티에 값을 할당할 때 호출된다.
enumarable : 나열 가능성으로, ture일 시 반복문 등을 통해 나열이 가능하며 false일 때는 나열이 불가능하다.
configurable : 설정 가능성으로, true일 시 프로퍼티 삭제 / 플래그 수정이 가능하며,
false일 때는 프로퍼티 삭제 플래그 수정이 불가능하다.
set 설명자의 인수가 하나인 이유는 간단한데,obj.propertyName = value;
와 같이 setter를 활용하므로, 인수는 value 하나이다.
데이터 프로퍼티와 동일하게 접근자 프로퍼티에도 defineProperty를 통해 getter, setter를 생성할 수 있다.
const obj = {
macro:'hi',
};
Object.defineProperty(obj, 'hello', {
get(){
return this.macro;
},
set(value){
this.macro = value;
}
});
console.log(obj.hello); // hi
obj.hello = 'hello world!';
console.log(obj.hello); // hello world!
Object.getOwnPropertyDescriptor(obj, 'hello');
// obj.hello 프로퍼티 또한 설명자 객체를 얻을 수 있으며
// 설명자 객체는 다음의 형태를 가진다.
// configurable: false
// enumerable: false
// get: ƒ get()
// set: ƒ set(value)
getter, setter 활용하기
getter, setter에 해당하는 접근자 프로퍼티에서 호출, 할당 시 추가 로직을 부여할 수 있다.
const obj = {
get name(){
return this._name;
},
set name(value){
if(value.length < 3){
console.log('이름은 3글자 이상이어야 합니다.');
return;
}
this._name = value;
}
};
obj.name = 'TT'; // 이름은 3글자 이상이어야 합니다.
console.log(obj.name); // undefined
obj.name = 'Tom';
console.log(obj.name); // Tom
다음과 같이 작성하면, obj.name 프로퍼티를 호출하면 get의 로직에 따르게 되고,
obj.name = value로 name 프로퍼티에 값을 할당하면 set의 로직에 따르게 된다.
set 메서드를 통해 name 프로퍼티에 3글자 미만의 이름을 할당할 수 없으므로 'TT'를 할당할 수 없고
'Tom'은 3글자 이상이므로 성공적으로 할당된다.
각 메서드 마지막에 위치한 _name 프로퍼티는 protected 속성이며, 객체 내부와 그 자손에서만 사용하겠다는 의미다.
물론, 관습상 _으로 시작하는 속성은 외부에서 호출하지 않는 것이지 '호출이 불가능한 속성은 아니다'.
이와 같이, 접근자 프로퍼티는 데이터 프로퍼티와 연관이 있다.
개발자가 임의로 데이터 프로퍼티를 검증하는 로직을 setter에 넣어서 원하는 동작을 구현할 수도 있다.
즉 객체의 속성 값에 대하여, 제약조건을 부여할 수도 있고 변경이 불가능하게 만들 수도 있다.
이후 사용처
다음의 getter, setter는 앞으로 다룰 Class와 Proxy 객체에서도 등장한다.
기본적인 작동 원리는 동일하다.
getter는 프로퍼티를 읽는 과정에 관여하며,
setter는 프로퍼티에 값을 할당할 때의 과정에 관여한다.
참고 출처
'JavaScript > theory' 카테고리의 다른 글
자바스크립트의 undefined, null에 대해 알아보자. (0) | 2022.01.19 |
---|---|
자바스크립트 클래스란? (0) | 2022.01.18 |
객체 프로퍼티 플래그와 설명자(Flag & Descriptor) (0) | 2022.01.17 |
래퍼 객체(Wrapper Object)란? (0) | 2022.01.14 |
[자바스크립트] V8 엔진의 메모리 관리 이해하기 (0) | 2022.01.12 |