객체의 프로퍼티는 크게 두 가지로 나뉜다.
1. 데이터 프로퍼티 (data property)
밑에서 배울 접근자 프로퍼티를 제외한 모든 프로퍼티.
2. 접근자 프로퍼티 (accessor property)
접근자 프로퍼티의 본질은 함수이다. 이 함수는 값을 획득(get) 하고 설정(set) 하는 역할을 담당한다.
let obj = {
get propName() {
// getter, obj.propName을 실행할 때 실행되는 코드
},
set propName(value) {
// setter, obj.propName = value를 실행할 때 실행되는 코드
}
};
getter 메서드는 obj.propName 을 사용해 프로퍼티를 읽으려고 할 때 실행되고, setter 메서드는 obj.propName = value 값 으로 프로퍼티에 값을 할당하려 할 때 실행된다.
let user = {
name: "mung",
surname: "sik",
get fullName() {
return `${this.name} ${this.surname}`;
}
};
console.log(user.fullName); // mung sik
접근자 프로퍼티를 사용하면 함수처럼 호출하지 않고, 일반 프로퍼티에서 값에 접근하는 것처럼 평범하게 user.fullName을 사용해 프로퍼티 값을 얻을 수 있다. 이 때, 위의 예시에는 getter 메서드만 있기 때문에 user.fullName = "Ramos" 라고 할당하면 에러 가 발생한다.
let user = {
name: "mung",
surname: "sik",
get fullName() {
return `${this.name} ${this.surname}`;
},
set fullName(value) {
[this.name, this.surname] = value.split(" ");
}
};
// 주어진 값을 사용해 set fullName이 실행됩니다.
user.fullName = "Sergio Ramos";
console.log(user.name); // Sergio
console.log(user.surname); // Ramos
getter와 setter 메서드를 구현하면 객체엔 fullName 이라는 가상의 프로퍼티가 생긴다. 가상의 프로퍼티는 읽고 쓸 순 있지만 실제로는 존재하지 않는다.
💨 getter 와 setter 활용하기
getter와 setter를 '실제' 프로퍼티 값을 감싸는 wrapper 처럼 사용하면, 프로퍼티 값을 원하는 대로 통제할 수 있다.
let user = {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName= lastName;
this.age = age;
}
get age() {
return this._age;
}
set age() {
if (value.length < 0) {
console.log("음수는 불가능합니다");
return;
}
this._age = value;
}
}
const user1 = new user('mung', 'sik', 28);
위 예시에서 age를 위한 setter 를 만들어 age 의 값이 음수가 되는걸 방지하고 있다.
이 때, 실제 값은 _age에 저장된다.
💨호환성을 키워보자.
데이터 프로퍼티 name 과 age 를 사용해서 사용자를 나타내는 객체를 구현한다고 가정한다.
function User(name, age) {
this.name = name;
this.age = age;
}
let Mung = new User("Mung", 28);
console.log( Mung.age ); // 28
그런데 요구사항이 바뀌어 age 대신 birthday를 저장해야한다. 이 때, 접근자 프로퍼티를 사용하지 않으면 위의 코드에서 힘들게 만들어놓은 age를 삭제하고 수정해야한다. 그러므로 age는 그대로두고 getter 와 setter을 이용해 birthday를 추가해보도록 하자.
function User(name, birthday) {
this.name = name;
this.birthday = birthday;
// age는 현재 날짜와 생일을 기준으로 계산됩니다.
Object.defineProperty(this, "age", {
get() {
let todayYear = new Date().getFullYear();
return todayYear - this.birthday.getFullYear();
}
});
}
let Mung = new User("Mung", new Date(1994, 9, 8));
console.log(Mung.birthday ); // birthday를 사용할 수 있습니다.
console.log( Mung.age ); // age 역시 사용할 수 있습니다.
✅ 위에서 사용한 Object.defineProperty 메서드의 문법은 다음과 같다.
Object.defineProperty(obj, propertyName, descriptor)
obj, propertyName : 설명자를 적용하고 싶은 객체와 객체 프로퍼티
descriptor : 적용하고자 하는 프로퍼티 설명자
difineProperty 메서드는 객체에 해당 프로퍼티가 있으면 플래그를 원하는데로 변경해준다. 프로퍼티가 없으면 인수로 넘겨받은 정보를 이용해 새로운 프로퍼티를 만든다. 이 때, 플래그 정보가 없으면 자동으로 false 가 된다.
{
"value": "Mung",
"writable": false,
"enumerable": false,
"configurable": false
}
따라서
let user = { };
Object.defineProperty(user, "name", {
value: "Mung",
// defineProperty를 사용해 새로운 프로퍼티를 만들 땐, 어떤 플래그를 true로 할지 명시해주어야 합니다.
enumerable: true,
configurable: true
});
alert(user.name); // Mung
user.name = "Lee"; // Error
'JS skills' 카테고리의 다른 글
7. 객체 안에 함수 저장하기 (0) | 2021.08.26 |
---|---|
6. prototype 과 this 를 통한 함수 재활용 (0) | 2021.08.26 |
4. window.location.reload() (0) | 2021.08.18 |
3. Element.disabled / Element.className (0) | 2021.08.18 |
2. inserAdjacentHTML() / setAttribute() (0) | 2021.08.18 |