被 Vue 管理的函数(如 datamethods、侦听器 handler、计算属性 get/set)→ 写成普通函数,this 指向 vm
不被 Vue 管理的回调(定时器 setTimeout/setInterval、ajax、Promise.then())→ 写成箭头函数,this 才指向 vm

为什么 setTimeout 要用箭头函数?

《025_watch对比computed》文中:

watch: {
  firstName(val) {
    //如果此处写为普通 function,this 将是 window(undefined 严格模式)
    setTimeout(() => {
      console.log(this)          // ✅ vm (Vue 实例)
      this.fullName = val + '-' + this.lastName
    }, 1000)
  }
}

原因分析:

1️⃣ firstName(val){...} —— Vue 帮你调用

Vue 内部用 call(vm)apply(vm) 调用这个 watcher handler,所以普通函数里 this === vm,没问题。

2️⃣ setTimeout(function(){...}) —— 浏览器调用,不是 Vue

setTimeout 的回调是浏览器异步队列调用的,普通 function 没有自身 this 绑定,会回退到:

  • 非严格模式 → window
  • 严格模式 → undefined

所以不能用普通函数,否则 this.fullName 会报错。

3️⃣ 箭头函数为什么行? //★★★

箭头函数没有自己的 this,它的 this 继承 自 外层 词法作用域——也就是外层 firstName(val){...} 里的 this(即 vm),所以:

setTimeout(() => {
  this.fullName = ... // this 沿作用域链找到 vm
})

记忆口诀(尚硅谷原话)

🔑 Vue 调的 → 普通函数(Vue 帮你绑 this)
🔑 JS 引擎/浏览器调的(定时器、ajax、Promise)→ 箭头函数(继承外层 this)

对照表格

场景 示例 推荐写法 this 是谁
data / methods / computed / watch handler Vue 调用 普通函数 vm
setTimeout / setInterval 浏览器调用 箭头函数 继承外层 → vm
axios().then(fn) / Promise.then() 微任务队列 箭头函数 继承外层 → vm
自定义指令 bind(el,binding,vnode){} Vue 调用 普通函数 vm(一般不用this)