개인공부/TIL(Today I Learned)

TIL 44일차_setTimeout의 this와 이를 제어하는 bind메소드

soon327 2021. 3. 3. 00:18

thisthis를 사용한 함수가 어떻게 불리느냐(어디에서 호출되느냐)에 따라 가리키는 값이 달라진다.

따라서 원하는 this를 지정해주기 위한 method가 있는데
바로 call, apply, bind 이다.
이중 callapply는 this를 지정해줌과 동시에 함수를 호출하며
bind는 호출하지 않는다는 차이점이 있다.

오늘은 bind를 사용하여 비동기함수인 setTimeout의 this를 제어해 보자.

왜 setTimeout의 this는 요상할까??

setTimeout의 this는 조금은 의도와는 다르게 작동한다.
strict모드일 때는 undefined가 호출되고,
strict모드가 아닐 때는, 전역객체 (window 혹은 global)가 호출된다.

왜일까??

이건 이벤트루프,스택,큐와 관련된 내용인데
앞서 말했듯이 setTimeout함수는 비동기함수이다.
따라서 setTimeout함수의 대상이되는 this는 콜스택에 들어갔다가, setTimeout함수를 web ApIs에 전달하고
콜스택에서 pop()된다.(👈)

이후, setTimeout에서 설정한 시간이 지나면, setTimeout의 매개변수로 들어간 실행함수가
태스크큐로 들어가고, 콜스택이 비면 이벤트루프에의해 콜스택으로 들어가 실행된다.
이때 즉, setTimeout의 실행함수가 실행될 때, 실행함수의 this는 ???
위의 (👈)에서 이미 pop()되어 사라졌다.
따라서 this값이 의도와다르게 설정되는 것이다.

bind로 setTimeout의 this 제어하기

setTimeout에 bind메소드를 사용할 떄는,
setTimeout의 실행함수에 사용해야한다!

//나의 실수
step() {
    setTimeout.bind(this, this.step, this.timeBetweenSteps);
  }

//올바른 사용
step() {
    setTimeout(this.step.bind(this), this.timeBetweenSteps);
  }

setTimeout 안에 익명함수를 넣을때는,
그냥 arrow function을 사용하면 된다.