접근자 프로퍼티는 앞서 소개한 데이터 프로퍼티와 같이 프로퍼티의 종류로서 자체적으로 값을 가지고 있지 않지만 다른 데이터 프로퍼티의 값을 읽거나(get) 재설정(set)할 때 사용하는 접근자 함수로 구성된 프로퍼티 입니다. 접근자 프로퍼티는 다음과 같은 프로퍼티 어트리뷰트를 갖습니다.
- [[Get]] : 프로퍼티의 데이터 프로퍼티의 값을 읽을 때 호출되는 접근자 함수이며 접근자 호출시 [[Get]]의 값인 getter 함수가 호출되어 그 수행 결과가 프로퍼티 값으로 반환됩니다.
- [[Set]] : 프로퍼티의 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수이며 접근자 호출시 [[Set]]의 값인 setter 함수가 호출되어 그 결과를 데이터 프로퍼티의 값으로 저장합니다.
- [[Enumerable]] : 데이터 프로퍼티의 설명과 동일
- [[Configurable]] : 데이터 프로퍼티의 설명과 동일
★ 접근자 프로퍼티의 어트리뷰트 중 Value와 Writable 속성이 없는 이유는, get과 set 프로퍼티는 그 자체로 값을 가지고 있기 때문이고, 마찬가지로 애초에 값이 없으니 수정도 불가능 하기 때문입니다.
// ① get과 set 함수의 기본 사용법 let recordScore = { _score: 0, // 관례적으로 키 앞에 언더스코어를 붙여 해당 프로퍼티가 외부에 노출되지 않고 가급적 내부에서 사용되어야 한다고 표시를 해줍니다. // getter 메서드 get getScore() { // 호출시 현재 객체의 변수를 반환하는 get 함수문 console.log('your score is'); return this._score; }, // setter 메서드 set setScore(score) { // 호출시 현재 객체의 변수를 사용자가 입력한 값으로 재할당 하는 set 함수문 console.log('setting score'); if(score > 100 || score < 0) console.log("please write the right bound of score"); else this._score = score; } }; // getter 호출 console.log(recordScore.getScore); // setter 호출 recordScore.setScore = 50; // getter 호출 console.log(recordScore.getScore);
이러한 접근자 프로퍼티의 용도는 데이터 프로퍼티와는 다르게 특정 값을 읽어오거나 수정하는대에 주 목적을 두고 있으며, 좀 더 세부적인 역할은 다음과 같습니다.
- 캡슐화 (Encapsulation) : 객체 내부의 상태를 외부에서 직접 접근하는 것을 제어하고, 값을 가져오거나 설정하는 과정을 감춤으로써 객체의 내부를 보호합니다.
let counter = { _count: 0, // counter 객체의 count 프로퍼티를 설정합니다. get count() { // count 정보를 반환하는 getter 설정 return this._count; }, set count(value) { // 사용자가 입력한 값을 count에 설정하는 setter 설정 if (value >= 0) { this._count = value; } else { console.log('Count cannot be negative.'); } }, // 값 증가 메서드 increment() { this._count++; } }; console.log(counterObj.count); // 0 counter.count = 5; console.log(counterObj.count); // 5 counter.count = -1; // Count cannot be negative. console.log(counterObj.count); // 5 (값이 변경되지 않음) counter.increment(); console.log(counterObj.count); // 6
- 유효성 검사 (Validation) : 값을 설정하기 전에 유효성을 검사하거나, 특정 조건을 체크하여 값을 설정하거나 반환할 수 있습니다.
let user = { _name: '', // 유저의 이름을 의미하는 name 프로퍼티를 빈 문자열로 초기화 set setName(newName) { // 해당 조건에 맞지 않을 경우 다음 문구 출력 (유효성 검사) if (newName.length > 5 || newName.length < 3) { console.log('Name is too short.'); } else { // 위의 조건에 맞지 않는, 즉 이름의 길이 범위 안에 들어온 경우 해당 이름으로 name을 설정 this._name = newName; } }, // getter 메서드 호출 get getName() { return this._name; } }; user.setName = '박종민'; console.log(user.getName); // 박종민 출력 user.setName = '종민'; // Name is too short. 문구 출력 console.log(user.getName); // 값이 변경 되지 않고 그대로 박종민 출력
- 동작 추가 (Behavior Addition) : 값이 읽힐 때나 설정될 때 특정 동작이 필요한 경우, 해당 동작을 추가할 수 있습니다. 한마디로 위의 캡슐화와 유효성 검사 등을 조합한 경우라고 보시면 됩니다.
const person = { _firstName: "Re", _lastName: "Go", get fullName() { return this._firstName + "_" + this._lastName; //get 함수에는 객체의 성과 이름을 이어 붙여 반환함으로 캡슐화를 추가했다고 볼 수 있습니다. }, set fullName(name) { // set 함수는 인자로 넘어온 값을 데이터 프로퍼티 값으로 새로 할당합니다. 이때 조건으로 넘어온 이름이 포맷 가능한 경우가 아닐 때(사용자가 이름을 2개가 아니라 1개 이하, 3개 이상으로 적었을 경우) 다음 문구를 출력하여 유효성 검사를 추가했다고 볼 수 있습니다. const parts = name.split(" "); if (parts.length === 2){ this._firstName = parts[0]; this._lastName = parts[1]; }else{ console.log('Invalid full name format.'); } } }; console.log(person.fullName); // fullName 접근자 프로퍼티를 통한 값 읽기 방법으로 getter 함수인 get fullName 함수가 실행되어 "Re_Go"를 반환 받아 출력합니다. person.fullName = "Park jongmin"; // // fullName 접근자 프로퍼티를 통한 값을 설정하여 setter 함수인 set fullName 함수가 실행되어 인자로 전달 받은 다음 문구를 각각 성과 이름 매개변수에 저장합니다. console.log(person.fullName); // set fullName 함수에 의해 재정의 된 매개 변수들을 get 함수를 호출하여 Park _jongmin"을 반환 받아 출력하게 됩니다.