TIL

20221116 TIL 다시 만난 자바스크립트 this

jiwoosmile 2022. 11. 16. 08:18

 

몇 주 전에 날을 잡고 반드시 this를 정복하리라 하고 this개념 정리를 했었는데,

(https://yomiju.tistory.com/254)

객체 지향적으로 UI 상태 관리를 하면서 this를 다시 만나게 되었다.

처음에는 원하는 대로 동작하지 않아 매우 당황스러웠고, 도대체 무엇이 문제인지 한참 찾아보았다.

그래도 한 번 정리를 해둔 덕분에 2시간 만에?! 문제를 해결할 수 있었다.

사실 정리를 했음에도 쓰면서 this가 무엇을 가리키는지 판단하지 않고 자바스크립트 클래스에서 자바처럼 썼다가

계속 있어야 되는 필드가 undefined여서 프로그램이 터지는 일이 발생했다.

앱이 장렬히 전사했다...

모든 코드를 다 돌아보다가 잘못된 부분이 없어서 믿고 있던 해당 부분의 this.schedule을 로그로 찍어봤는데 계속 에러가 나서

this를 로그로 찍어봤더니 this가 undefined였다...

this를 잘못 다루고 있는 게 문제였음을 깨닫고, 수정하여 원하는 결과를 얻을 수 있었다.

이것을 만드는 게 이토록 심오했다니..!

그런데 메서드를 화살표 함수로 정의할지, 그냥 일반적인 함수 선언으로 정의할 지 고민이 조금 되었다.

일반적인 함수 선언으로 메서드를 선언하는 경우에 이벤트 리스너에 콜백을 등록할 때 

onClick={() => timerStore.moveToNextSchedule()}

이와 같이 객체.메서드() 형식을 이용해야 메서드에서 쓰인 this가 객체에 바인딩된다.

 

onClick={timerStore.moveToNextSchedule}

이렇게 작성하면 moveToNextSchedule에서 쓴 this에 이 함수를 실행하는 객체가 들어가고,

timerStore.moveToNextSchedule을 실행하는 주체는 timerStore가 아니기 때문에 원하는 대로 작동하지 않는다.

 

만약 moveToNextSchedule이 아래와 같이 화살표 함수로 정의되었다면

class TimerStore {
  moveToNextSchedule = () => {
    // this instanceof TimerStore === true 
  }
}

이 코드는 아래의 코드에 대한 syntax sugar이기 때문에

class TimerStore {
  constructor() {
    // this instanceof TimerStore === true 
    this.moveToNextSchedule = () => {
      // this instanceof TimerStore === true 
    }
  }
}

위의 코드와 동일한 상태가 된다.

따라서 화살표 함수 내부에서 this가 해당 클래스로 정해지기 때문에 

onClick={timerStore.moveToNextSchedule}

위 코드처럼 사용하거나, 심지어 구조 분해를 이용해서 '객체.' 없이 사용해도 문제가 없다.

 

메서드를 화살표 함수로 정의할지, 그냥 일반적인 함수 선언으로 정의할 지 고민이 조금 되었기 때문에 질문을 남겼고,

아샬님께서 일반적인 함수 선언으로 정의하는 것이 메서드고, 메서드는 그렇게 쓰는 것이라고 말씀해주셨다.

왜냐하면 화살표 함수는 프로토타입에 들어가지 않고, 타입이 함수인 프로퍼티에만 해당하기 때문에

일반적인 메서드로 생각하고 사용하기 어렵기 때문이다.

 

고민은 종료되었다.

앞으로는 일반적인 함수 선언으로 메서드를 정의하고,

메서드를 실행할 때 꼭 앞에 객체를 붙여주고,

만약 콜백으로 넣어줘야 한다면 화살표 함수꼴로 () => 객체.메서드()로 넣어주도록 하자.

 

this에 대해 공부해두지 않았다면 정말 혼란스러웠을 것 같고,

개념 공부의 중요성을 다시 한 번 깨닫게 된 것 같다.

잘 모르면서 사용하는 것만큼 위험한 게 없는 것 같다.

개념 공부도 꼭 잘 챙기자.