우아한 테크코스에서 진행한 프로젝트 중 하나인 브릿지게임 프로젝트를 진행하던 중 코드를 분리하여 서로 영향을 받지 않도록 하고, 코드의 효율적인 재사용을 위해 MVC 디자인 패턴을 사용하여 리팩토링을 진행중이었습니다.
입력을 받는 부분을 InputView객체에 만들었고, 입력받은 값을 통해 처리를 Controller 부분에서 하려고 했습니다.
Controller의 requestBridgeSize 함수에서 InputView의 readBridgeSize 함수를 호출하면서 콜백함수로 Controller의 내부 메서드인 this.checkBridgeSize 함수를 넘겨줬습니다.
InputView의 readBridgeSize함수를 통해 Console.readLine()를 사용하여 사용자에게 입력값을 받고, 콜백함수로 넘겨줬습니다.
콜백함수인 checkBridgeSize(size)함수에서 입력값을 받고, 유효성 검사를 진행했습니다. 이후 검사를 통과하면 Controller 내부 메서드인 this.setGame()를 호출하는데 아래와 같은 문제가 발생했습니다.
undefined을 읽을수 없다?
어느 부분이 문제인지 한참을 고민하다가 this를 console.log로 찍어봤습니다.
this의 값이 없다???????????
대부분의 경우 this의 값은 함수를
호출한 방법에 의해 결정
됩니다.
출처 : JavascriptMDN
그렇다면 어디서 호출이 되었는가? 다시 처음부터 차근차근 알아보겠습니다.
참조 : 참조 NodeJs 공식문서
this는 전역객체를 가리키는 것입니다.
최종적으로 this는 전역객체인 global 객체를 가리키게 됩니다.
하지만 console.log를 통해 this를 확인 했을때 왜 this는 global객체가 아닌 undefined가 출력이 될까요?결과 => undefinded
결과 => global객체
클래스는 따로 stict모드를 선언하지 않아도 strict모드가 적용되어 있으며, strict모드가 적용되었을때 일반함수에서의 this는 undefined를 가리키게 됩니다.
따라서 클래스 내부에서 선언한 일반함수의 this는 전역객체인 global객체를 가리키는것이 아닌 undefined를 나타냅니다.
이와 반대로 클래스 외부에서 선언된 일반함수의 this는 strict모드가 적용되지 않아 this가 가리키는것은 전역객체인 global객체를 가리키게 되는것입니다.
this.setGame의 this를 현재 BridgeController 클래스의 this로 바꿔주면 됩니다.
이를 해결하기 위해서 처음 InputView의 readBridgeSize 함수를 호출한 부분으로 돌아가서 bind함수를 통해 this를 넘겨줍니다.
이때 넘겨주는 this는 클래스의 메서드에서 호출한 this이기 때문에 BridgeController 클래스가 만든 인스턴스를 바인딩 하게 됩니다.
bind함수에 대해 궁금하시다면 → Javascript MDN