
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 역시 그대로 사용할 수 있습니다.