[vue] setTimeout - this

1. 상황

vue에서 setTimeout에 익명함수 넣고, 그 내부에서 this로 함수를 호출하면 is not a function 에러가 발생합니다.

<template>
  <div>
    안녕하세요
  </div>
</template>

<script>
export default {
  name: 'App',
  created() {
    setTimeout(function() {
      console.log('this', this) // window
      this.sayHi()
    })
  },
  methods: {
    sayHi() {
      console.log('sayHi')
    }
  }
}
</script>

2. 원인

자바스크립트 this는 4가지 상황에서 의미가 다릅니다.

setTimeout의 첫번째 인자로 익명 함수 function() {} 을 전달했고 일반함수처럼 호출됩니다.

    1. 일반 함수 호출 - 전역 객체
    1. 메서드 호출 - 메서드를 호출한 객체
    1. 생성자 함수 호출 - 생성자가 호출할 인스턴스
    1. apply, call, bind 메서드에 의한 간접 호출 - 메서드의 첫번째 인수로 전달한 객체

3. 해결방법

1) 화살표 함수

호출되는 상황에 따라 동적으로 this가 결정되는 일반함수와 다르게 화살표 함수는 선언 시점에 this가 정의됩니다.

화살표 함수 내부에는 this가 없기 때문에 상위 스코프로 올라가다가 가장 유사한 환경을 만나면 탐색을 그만둡니다.

가장 먼저 만나게 되는 this는 vue 인스턴스 이기 때문에 vue인스턴스가 바인딩됩니다.

setTimeout(() => {
	console.log('setTimeout', this) // proxy
	this.sayHi()
})

2) 인스턴스 참조

음 인스턴스를 다른 변수에 참조걸어놓고 사용하는건데, 조금 비효율적

const vm = this

setTimeout(function() {
	console.log('setTimeout', vm) // Proxy {sayHi: ƒ, a: ƒ, …}
	vm.sayHi()
})

3) prototype bind

익명함수에 this를 바인딩 하는 방법

참고로 화살표함수는 바인딩 안된다.

setTimeout(function() {
	console.log('setTimeout', this)
 	this.sayHi()
}.bind(this))

4. 결론

this 언제 어떻게 사용되는지 잘 알아보고

화살표 함수 잘 사용하자.

좋은 웹페이지 즐겨찾기