Summary of: https://javascript.info/property-accessors
객체의 프로퍼티는 두 종류로 나뉜다.
접근자 프로퍼티는 getter
와 setter
메소드로 표현된다.
let user = {
name: "John",
surname: "Smith",
get fullName() {
return `${this.name} ${this.surname}`;
},
set fullName(value) {
[this.name, this.surname] = value.split(" ");
}
};
// 주어진 값을 사용해 set fullName이 실행됩니다.
user.fullName = "Alice Cooper";
alert(user.name); // Alice
alert(user.surname); // Cooper
user.fullName=
을 사용해 값 할당 시 에러 발생fullName
은 가상의 프로퍼티다. 읽고 쓸 수 있지만 실제로 존재하지 않음접근자 프로퍼티의 설명자(descriptors)에는 value
와 writable
가 없는 대신에 get
과 set
이라는 함수가 있다.
따라서 접근자 프로퍼티는 다음과 같은 설명자를 갖는다.
get
– 인수가 없는 함수로, 프로퍼티를 읽을 때 동작함set
– 인수가 하나인 함수로, 프로퍼티에 값을 쓸 때 호출됨enumerable
– 데이터 프로퍼티와 동일함configurable
– 데이터 프로퍼티와 동일함아래와 같이 defineProperty
에 설명자 get
과 set
을 전달하면 fullName
접근자 생성이 가능하다.
let user = {
name: "John",
surname: "Smith"
};
Object.defineProperty(user, 'fullName', {
get() {
return `${this.name} ${this.surname}`;
},
set(value) {
[this.name, this.surname] = value.split(" ");
}
});
alert(user.fullName); // John Smith
for(let key in user) alert(key); // name, surname
프로퍼티는 데이터 프로퍼티나 접근자 프로퍼티 중 한 종류에만 속할 수 있다.
교집합은 존재하지 않는다. 따라서 get/set
메서드와 value
를 둘 다 설정하면 에러가 발생한다.
실제 값은 _name
이라는 private 변수에 별도로 저장하면서 setter
를 이용해 name
의 입력을 통제한다.
let user = {
get name() {
return this._name;
},
set name(value) {
if (value.length < 4) {
alert("입력하신 값이 너무 짧습니다. 네 글자 이상으로 구성된 이름을 입력하세요.");
return;
}
this._name = value;
}
};
user.name = "Pete";
alert(user.name); // Pete
user.name = ""; // 너무 짧은 이름을 할당하려 함
사실 user._name
을 통해 외부에서 접근할 수 있긴 하지만 가능하면 건드리지 않는 것이 관습이다.
function User(name, age) {
this.name = name;
this.age = age;
}
let john = new User("John", 25);
alert( john.age ); // 25
위의 코드에서 만약 age
대신 더욱 정확하고 편리한birtyday
를 써야 한다는 요구를 받는다면?
만약 생성자 함수를 직접 수정하면 기존에 age
를 사용하는 모든 코드를 찾아서 일일이 수정해야 하는 번거로움이 있다.
여기서 age
를 위한 getter
를 추가한다면 (=접근자를 생성한다면) 문제를 쉽게를 해결할 수 있다.
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 john = new User("John", new Date(1992, 6, 1));
alert( john.birthday ); // birthday를 사용할 수 있습니다.
alert( john.age ); // age 역시 그대로 사용할 수 있습니다.