class User {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
}
const user1 = new User('Steve', 'Job', -1);
// 사용자가 실수로 나이를 -1 로 지정했다고 가정
console.log(user1.age);
// -1
하지만 사람의 나이가 -1 이라는 것은 말이 안된다.
이렇게 Class
를 사용하는 사용자 혹은 우리가 잘못 사용해도 방어적인 자세로 만들 수 있도록 해주는 것이 Getter and Setters
이다.
class User {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
// get 이라는 키워드를 이용해서 값을 리턴하고
get age() {
return this.age
}
// set 이라는 키워드를 이용해서 값을 설정할 수 있다.
// 대신 set은 값을 설정하기 때문에 value를 받아와야 한다.
set age(value) {
this.age = value;
}
}
위와 같은 코드로 작성 시, call stack
에러가 발생할 것이다.
get age() {
return this.age
}
우리가 age 라는 getter를 정의하는 순간
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
의 this.age
는 메모리에 올라간 데이터를 읽어오는게 아니라 바로 getter
를 호출
하게 된다.
그리고
set age(value) {
this.age = value;
}
우리가 setter
를 정의하는 순간 this.age = age;
의 = age;
즉, 값을 할당할 때 바로 메모리에 값을 할당하는 것이 아니라 setter
를 호출
하게 된다.
이 말은 우리가 setter
안에서 전달된 value
를 this.age
에 할당할 때, 메모리의 값을 업데이트 하는 것이 아니라 setter
를 호출
하게 된다.
이렇게 계속 무한반복
이 되다 보니까 콜스택이 초과됐다는(call stack size exceeded)
에러가 발생하는 것이다.
위와 같은 에러를 방지하기 위해서는 getter
와 setter
안에서 쓰여지는 변수 이름을 다르게 만들어줘야 한다.
get age() {
return this._age
}
set age(value) {
this._age = value;
}
보통 일반적으로 변수명 맨 앞에 _ 기호를 넣어 getter와 setter의 변수명을 만든다.
// 방법 1
set age(value) {
if (value < 0) {
throw Error('age can not be negative');
}
this._age = value;
}
// 방법 2
set age(value) {
// 삼항연산자를 활용, value가 0보다 작다면 0을 기입, 그렇지 않다면 value를 사용하겠다.
this._age = value < 0 ? 0 : value;
}
setter
가 있기 때문에 최종적으로 사용자가 나이를 -1로 기입하는 실수를 저지르더라도 에러를 띄움으로써 잘못된 데이터 기입을 방지
할 수 있다.