드림코딩아카데미의 당근게임만들기를 하면서 최종적으로 refactoring할때 배운 것인데, 클래스들로 각 기능들을 묶고 c++처럼 private 기능을 주고 싶거나 오브젝트 생성시 필수로 필요한 인자들과 옵셔널적으로 설정할 수 있는 인자들을 명확하게 구별할 때 쓰면 좋다. 하나의 함수에 이름 없는 수많은 인자들을 전달해야하는 기존의 방식을 개선해 가독성을 높이는 것이 장점이다.
<script type="txt/javascript">
export class GameBuilder {
withGameDuration(duration) {
this.gameDuration = duration;
return this;
}
withCarrotCount(num) {
this.carrotCount = num;
return this;
}
withBugCount(num) {
this.bugCount = num;
return this;
}
build() {
return new Game(this.gameDuration, this.carrotCount, this.bugCount)
}
}
class Game {
constructor(gameDuration, carrotCount, bugCount) {
this.gameDuration = gameDuration;
this.carrotCount = carrotCount;
this.bugCount = bugCount;
.
.
.
}
const game = new GameBuilder()
// GameBuilder오브젝트가 생성됨
.withGameDuration(5)
.withCarrotCount(5)
.withBugCount(5)
// 각각 함수에서 return this 하므로 위에서 생성된 Game Builder 오브젝트가 리턴됨
.build();
//최종적으로 build에서 Game 오브젝트가 리턴됨
}
</script>
클래스 GameBuilder에 return this를 써주면 클래스 자체를 리턴해준다. (메소드마다 return this를 하는 이유)
withGameDuration(duration) {
this.duration = duration
}
return this를 써놓지 않으면 사람들이 사용할때 일일이 계속 builder.을 반복해서 써야 한다.
const builder = new GameBuilder();
builder.withGameDuration(4);
builder.withCarrotCount(4);
하지만 withGameDuration에서 전달된 duration을 설정하고 그 클래스 자체를 리턴하게 되면 사용하는 곳에서 builder.를 반복해서 호출하지 않아도 된다.
new GameBuilder()
.withGameDuration(4)
.withCarrotCount(4);
따라서 GameBuilder 클래스를 이용해 새로운 인스턴스 game을 만들어서 각 메소드들을 전달해서 정확하게 어떤 의미로 인자를 보내는지 인지하면서 원하는 기능을 실행시킨다.
🤓 자바스크립트에서는 클래스에 있는 함수를 누군가에게 전달해줄때는 클래스 정보가 무시된다.(함수를 클래스와 바인딩해줘야함)
class Field{
this.field.addEventListener("click", this.onClick);
}
이 경우, this는 클래스 정보를 담지 않는다.
자바스크립트에서 this는 동적(누가 호출하느냐에 따라 결정니깐)
✏️ this는 어떤 클래스 안에 있는 함수를 다른 콜백으로 전달할때는 그 함수에 포함 되어있는 클래스의 정보가 사라진다. 그래서 클래스와 이 함수를 묶을 수 있는 this binding을 해야 한다.
<script type="txt/javascript">
// this binding 하기
// 3가지 방법
// 1. bind함수 사용
this.onClick = this.onClick.bind(this);
// 2. 화살표함수 사용
this.field.addEventListener("click", (event) => {
this.onClick(event);
})
// 3. 함수를 변수로 만들어주고 화살표 함수로 변경
onClick = (e) => {
.
.
.
}
<script>
위의 방법 중 하나로 this를 바인딩 시키면, onClick은 class와 바인딩되었기 때문에 this.onClick를 전달하게 되었을때 this가 클래스이라는 것을 이제 인지하고 클래스에 등록된 함수라는 걸 알게 된다.
함수를 호출할 때 인수를 전달하거나 어떤 문자열을 적용할때 직접 쓰는 문자열은 오타를 만들 수 있다. 그래서 상수로 지정하거나 Object.freeze()를 이용할 수 있다.
export const Reason = Object.freeze({
win: "win",
lose: "lose",
cancel: "cancel",
});
game.setGameStopListener((reason) => {
let message;
switch (reason) {
case Reason.cancel: // 객체의 프로퍼티 사용
message = "Reply?";
break;
case Reason.win: // 객체의 프로퍼티 사용
message = "YOU WON";
break;
case Reason.lose: // 객체의 프로퍼티 사용
message = "YOU LOST";
break;
default:
throw new Error("not valid reason");
}
});
출처
드림코딩아카데미 브라우저 101 강의 듣고 적은 내용