[vue] setTimeout - this

6612 ワード

1.状況


vueがsettimeoutに匿名関数を入れ、その内部でこの関数を呼び出すと、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.原因


JavaScript thisは4つの場合に異なる意味を持つ.
settimeoutの最初のパラメータとして、匿名関数function() {}が渡され、通常の関数のように呼び出された.

  • 呼び出し
  • 一般関数-グローバルオブジェクト

  • 呼び出し
  • メソッド-呼び出しメソッドのオブジェクト

  • 呼び出し
  • ジェネレータ関数-ジェネレータが呼び出すインスタンス
  • apply、call、bindメソッドによって間接的に呼び出される-メソッドの最初の引数として渡されるオブジェクト
  • .

    3.解決方法


    1)矢印関数


    矢印関数は、通常の関数とは異なり、宣言時にこの値を定義します.これは呼び出しの状況によって異なります.
    矢印関数の内部に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


    匿名関数にバインドする方法
    矢印関数はバインドできません.
    setTimeout(function() {
    	console.log('setTimeout', this)
     	this.sayHi()
    }.bind(this))

    4.結論


    thisの使用方法を理解する
    矢印関数をよく使います.