자바스크립트에는 C와 같은 언어와 달리 public, private 같은 키워드가 없다. 그래서 직접 객체의 속성을 찾는 것보다, getter
,setter
를 사용하는 것이 좋다.
왜 이런지에 대한 이유를 설명하기 전에, getter
,setter
를 설명하겠다.
자바스크립트에는 두가지 프로퍼티(속성)가 있다.
- Data property (데이터 프로퍼티)
- Accessor property (접근자 프로퍼티)
getter
,setter
는 거의 모든 객체 지향 프로그래밍 언어에 존재한다.
접근자 프로퍼티는 getter(획득자)
와 setter(설정자)
메소드로 표현된다.
getter
를 활용하면 외부의 코드에서 프로퍼티(속성)들의 값을 얻을('get') 수 있고,setter
를 활용하면 그 값들을 바꾸어('set')줄 수 있다.
let obj = {
get propName() {
// getter, obj.propName을 실행할 때 실행되는 코드
},
set propName(value) {
// setter, obj.propNAme = value를 실행할 때 실행되는 코드
}
};
JS clean code 자료에 따르면,
- set할때 검증로직을 추가하는 것이 코드를 더 간단하게 만든다.
- 내부용 API를 캡슐화 할 수 있다.
- getting과 setting할 때 로그를 찾거나 에러처리를 하기 쉽다.
- 서버에서 객체 속성을 받아올 때 lazy load 할 수 있다.
아래의 예시를 보자.
// 나쁜 예
function makeBankAccount() {
// ...
return {
// ...
balance: 0
};
}
const account = makeBankAccount();
account.balance = 100;
// 좋은 예
function makeBankAccount() {
// private으로 선언된 변수
let balance = 0;
// 아래 return을 통해 public으로 선언된 "getter"
function getBalance() {
return balance;
}
// 아래 return을 통해 public으로 선언된 "setter"
function setBalance(amount) {
// ... balance를 업데이트하기 전 검증로직
balance = amount;
}
return {
// ...
getBalance,
setBalance
};
}
const account = makeBankAccount();
account.setBalance(100);
좋은 예에서는 나쁜 예에서와 달리, setBalance를 통해 balance의 값을 set하여 amount와 동일한 것을 확실히 하고, getBalance로 그 값을 get하는 것을 볼 수 있다.
이는 코드의 가독성도 높이고, 추가적인 검증을 거치면서, 에러처리도 쉽게할 수 있도록 한다.
// 나쁜 예
const Employee = function(name) {
this.name = name;
};
Employee.prototype.getName = function getName() {
return this.name;
};
const employee = new Employee('John Doe');
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
delete employee.name;
console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined
나쁜 예시에서는 delete employee.name
을 했음에도 불구하고, console.log
를 해보았을 때 여전히 employee.name
이 남아있음을 알 수 있다.
// 좋은 예
function makeEmployee(name) {
return {
getName() {
return name;
},
};
}
const employee = makeEmployee('John Doe');
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
delete employee.name;
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe